Concurrent ProgrammingNovember 18, 2009Concurrent ProgrammingNovember 18, 2009TopicsTopics Limitations of iterative servers Process-based concurrent servers Event-based concurrent servers Threads-based concurrent servers15-213Class23.ppt–2–15-213, F’09Concurrent Programming is Hard!Concurrent Programming is Hard!zzThe human mind tends to be sequentialThe human mind tends to be sequentialzzThe notion of time is often misleadingThe notion of time is often misleadingzzThinking about all possible sequences of events in a computer Thinking about all possible sequences of events in a computer system is at least error prone and frequently impossiblesystem is at least error prone and frequently impossiblezzClassical problem classes of concurrent programs:Classical problem classes of concurrent programs: Races: outcome depends on arbitrary scheduling decisions elsewhere in the systemz Example: who gets the last seat on the airplane? Deadlock: improper resource allocation prevents forward progressz Example: traffic gridlock Lifelock / Starvation / Fairness: external events and/or system scheduling decisions can prevent sub-task progressz Example: people always jump in front of you in linezzMany aspects of concurrent programming are beyond the Many aspects of concurrent programming are beyond the scope of 15scope of 15--213213–3–15-213, F’09Client / ServerSessionEcho Server OperationEcho Server OperationClientServersocket socketbindlistenrio_readlinebrio_writenrio_readlinebrio_writenConnectionrequestrio_readlinebclosecloseEOFAwait connectionrequest fromnext clientopen_listenfdopen_clientfdacceptconnect–4–15-213, F’09Iterative ServersIterative ServersIterative servers process one request at a time.Iterative servers process one request at a time.client 1 server client 2call connectcall acceptret connectret acceptcall connectcall writereadret writecloseclosecall acceptret connectcall writeret writeclosereadret acceptclose–5–15-213, F’09Fundamental Flaw of Iterative ServersFundamental Flaw of Iterative ServersSolution: use Solution: use concurrent servers concurrent servers instead.instead. Concurrent servers use multiple concurrent flows to serve multiple clients at the same time.client 1 server client 2call connectcall acceptcall readret connectret acceptcall connectcall fgetsUser goesout to lunchClient 1 blockswaiting for userto type in dataClient 2 blockswaiting to completeits connection request until afterlunch!Server blockswaiting fordata fromClient 1–6–15-213, F’09Concurrent Servers:Multiple ProcessesConcurrent Servers:Multiple ProcessesConcurrent servers handle multiple requests concurrently.Concurrent servers handle multiple requests concurrently.client 1 server client 2call connectcall acceptcall readret connectret acceptcall connectcall fgetsforkchild 1User goesout to lunchClient 1 blockswaiting for user to type in datacall acceptret connectret acceptcall fgetswriteforkcall readchild 2writecall readend readcloseclose...–7–15-213, F’09Three Basic Mechanisms for Creating Concurrent FlowsThree Basic Mechanisms for Creating Concurrent Flows1. Processes1. Processes Kernel automatically interleaves multiple logical flows. Each flow has its own private address space.2. Threads2. Threads Kernel automatically interleaves multiple logical flows. Each flow shares the same address space.3. I/O multiplexing with 3. I/O multiplexing with select()select() User manually interleaves multiple logical flows. Each flow shares the same address space. Popular for high-performance server designs.–8–15-213, F’09Review: Sequential ServerReview: Sequential Serverint main(int argc, char **argv) {int listenfd, connfd;int port = atoi(argv[1]);struct sockaddr_in clientaddr;int clientlen = sizeof(clientaddr);listenfd = Open_listenfd(port);while (1) {connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);echo(connfd);Close(connfd);}exit(0);} Accept a connection request Handle echo requests until client terminates–9–15-213, F’09Inner Echo LoopInner Echo Loopvoid echo(int connfd) {size_t n; char buf[MAXLINE]; rio_t rio;Rio_readinitb(&rio, connfd);while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {printf("server received %d bytes\n", n);Rio_writen(connfd, buf, n);}} Server reads lines of text Echos them right back–10–15-213, F’09Echo Server: accept IllustratedEcho Server: accept Illustratedlistenfd(3)Client1. Server blocks in accept, waiting for connection request on listening descriptor listenfd.clientfdServerlistenfd(3)ClientclientfdServer2. Client makes connection request by calling and blocking in connect.Connectionrequestlistenfd(3)ClientclientfdServer3. Server returns connfd from accept. Client returns from connect. Connection is now established between clientfdand connfd.connfd(4)–11–15-213, F’09int main(int argc, char **argv) {int listenfd, connfd;int port = atoi(argv[1]);struct sockaddr_in clientaddr;int clientlen=sizeof(clientaddr);Signal(SIGCHLD, sigchld_handler);listenfd = Open_listenfd(port);while (1) {connfd = Accept(listenfd, (SA *) &clientaddr, &clientlen);if (Fork() == 0) { Close(listenfd); /* Child closes its listening socket */echo(connfd); /* Child services client */Close(connfd); /* Child closes connection with client */exit(0); /* Child exits */}Close(connfd); /* Parent closes connected socket (important!) */}}Process-Based Concurrent ServerProcess-Based Concurrent ServerFork separate process for each clientDoes not allow any communication between different client handlers–12–15-213, F’09Process-Based Concurrent Server(cont)Process-Based Concurrent Server(cont)void sigchld_handler(int sig) {while (waitpid(-1, 0, WNOHANG) > 0);return;} Reap all zombie children–13–15-213, F’09Process Execution ModelProcess Execution Model Each client handled by independent process No shared state between them When child created, each have copies of listenfd and connfdz Parent must close connfd, child must close listenfdClient 1ServerClient 2ServerListeningServerConnection RequestsClient 1 data Client 2 data–14–15-213, F’09Implementation Issues With Process-Based DesignsImplementation Issues With Process-Based DesignsServer must reap zombie childrenServer must reap zombie children to avoid fatal memory leak.Server must Server must closecloseits copy of its copy of connfdconnfd.. Kernel keeps reference for each socket. After fork,
View Full Document