Page 1Concurrent ProgrammingNovember 30, 2007Concurrent ProgrammingNovember 30, 2007TopicsTopics Event-based concurrent servers Shared variables The need for synchronization Synchronizing with semaphores15-213“The course that gives CMU its Zip!”lecture-25.ppt–2–15-213, F’07Three 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 space2. Threads2. Threads Kernel automatically interleaves multiple logical flows Each flow shares the same address space3. I/O multiplexing with 3. I/O multiplexing with select()select() Application “manually” interleaves multiple logical flows Each flow shares the same address space Popular for high-performance server designs–3–15-213, F’07Appr. #3: Event-Based Concurrent Servers Using I/O MultiplexingAppr. #3: Event-Based Concurrent Servers Using I/O MultiplexingMaintain a pool of connected descriptorsMaintain a pool of connected descriptorsRepeat the following forever:Repeat the following forever: Use the Unix select function to block until:z (a) New connection request arrives on the listening descriptorz (b) New data arrives on an existing connected descriptor If (a), add the new connection to the pool of connections If (b), read any available data from the connectionz Close connection on EOF and remove it from the pool–4–15-213, F’07The select FunctionThe select Functionselect()select()sleeps until one or more file descriptors in the set sleeps until one or more file descriptors in the set readsetreadsetready for readingready for reading#include <sys/select.h>int select(int maxfdp1, fd_set *readset, NULL, NULL, NULL);readset• Opaque bit vector (max FD_SETSIZE bits) that indicates membership in a descriptor set• If bit k is 1, then descriptor k is a member of the descriptor setmaxfdp1• Maximum descriptor in descriptor set plus 1• Tests descriptors 0, 1, 2, ..., maxfdp1 - 1 for set membershipselect()select()returns the number of ready descriptors and sets each bit of returns the number of ready descriptors and sets each bit of readsetreadsetto indicate the ready status of its corresponding descriptorto indicate the ready status of its corresponding descriptor–5–15-213, F’07Macros for Manipulating Set DescriptorsMacros for Manipulating Set Descriptorsvoid void FD_ZERO(fd_setFD_ZERO(fd_set**fdsetfdset);); Turn off all bits in fdsetvoid void FD_SET(intFD_SET(intfdfd, , fd_setfd_set**fdsetfdset);); Turn on bit fd in fdsetvoid void FD_CLR(intFD_CLR(intfdfd, , fd_setfd_set**fdsetfdset);); Turn off bit fd in fdsetintintFD_ISSET(intFD_ISSET(intfdfd, *, *fdsetfdset);); Is bit fd in fdset turned on?–6–15-213, F’07Overall StructureOverall Structurelistenfd10clientfd74-1-1125-1-1-10123456789•••ActiveInactiveActiveNever UsedManage Pool of ConnectionsManage Pool of Connections listenfd: Listen for requests from new clients Active clients: Ones with a valid connectionUse select to detect activityUse select to detect activity New request on listenfd Request by active clientRequired ActivitiesRequired Activities Adding new clients Removing terminated clients EchoingPage 2–7–15-213, F’07Representing Pool of ClientsRepresenting Pool of Clients/* * echoservers.c - A concurrent echo server based on select */ #include "csapp.h" typedef struct { /* represents a pool of connected descriptors */ int maxfd; /* largest descriptor in read_set */ fd_set read_set; /* set of all active descriptors */ fd_set ready_set; /* subset of descriptors ready for reading */ int nready; /* number of ready descriptors from select */ int maxi; /* highwater index into client array */ int clientfd[FD_SETSIZE]; /* set of active descriptors */ rio_t clientrio[FD_SETSIZE]; /* set of active read buffers */ } pool; int byte_cnt = 0; /* counts total bytes received by server */ –8–15-213, F’07Pool ExamplePool Example maxfd = 12 maxi = 6 read_set = { 3, 4, 5, 7, 10, 12 }10clientfd74-1-1125-1-1-10123456789•••ActiveInactiveActiveNever Usedlistenfd = 3 –9–15-213, F’07Main LoopMain Loopint main(int argc, char **argv) { int listenfd, connfd, clientlen = sizeof(struct sockaddr_in); struct sockaddr_in clientaddr; static pool pool; listenfd = Open_listenfd(argv[1]); init_pool(listenfd, &pool); while (1) { pool.ready_set = pool.read_set; pool.nready = Select(pool.maxfd+1, &pool.ready_set, NULL, NULL, NULL); if (FD_ISSET(listenfd, &pool.ready_set)) { connfd = Accept(listenfd, (SA *)&clientaddr,&clientlen); add_client(connfd, &pool); } check_clients(&pool);} }–10–15-213, F’07Pool InitializationPool Initialization/* initialize the descriptor pool */void init_pool(int listenfd, pool *p) { /* Initially, there are no connected descriptors */ int i; p->maxi = -1; for (i=0; i< FD_SETSIZE; i++) p->clientfd[i] = -1; /* Initially, listenfd is only member of select read set */ p->maxfd = listenfd; FD_ZERO(&p->read_set); FD_SET(listenfd, &p->read_set); } –11–15-213, F’07Initial PoolInitial Pool maxfd = 3 maxi = -1 read_set = { 3 }-1clientfd-1-1-1-1-1-1-1-1-10123456789•••Never Usedlistenfd = 3 –12–15-213, F’07Main LoopMain Loopint main(int argc, char **argv) { int listenfd, connfd, clientlen = sizeof(struct sockaddr_in); struct sockaddr_in clientaddr; static pool pool; listenfd = Open_listenfd(argv[1]); init_pool(listenfd, &pool); while (1) { pool.ready_set = pool.read_set; pool.nready = Select(pool.maxfd+1, &pool.ready_set, NULL, NULL, NULL); if (FD_ISSET(listenfd, &pool.ready_set)) { connfd = Accept(listenfd, (SA *)&clientaddr,&clientlen); add_client(connfd, &pool); } check_clients(&pool);} }Page 3–13–15-213, F’07Adding ClientAdding Clientvoid add_client(int connfd, pool *p) /* add connfd to pool p */{ int i; p->nready--; for (i = 0; i < FD_SETSIZE; i++) /* Find available slot */ if (p->clientfd[i] < 0) {p->clientfd[i] = connfd; Rio_readinitb(&p->clientrio[i], connfd); FD_SET(connfd, &p->read_set); /* Add desc to read set */ if (connfd > p->maxfd) /* Update max descriptor num */p->maxfd = connfd; if (i > p->maxi) /* Update pool high water mark */p->maxi = i; break; } if (i == FD_SETSIZE) /* Couldn't find an empty slot */ app_error("add_client error: Too many clients"); } –14–15-213, F’07 maxfd = 12
View Full Document