/
Chapter  Concurrent Programming As we learned in Chapt Chapter  Concurrent Programming As we learned in Chapt

Chapter Concurrent Programming As we learned in Chapt - PDF document

mitsue-stanley
mitsue-stanley . @mitsue-stanley
Follow
399 views
Uploaded On 2015-05-19

Chapter Concurrent Programming As we learned in Chapt - PPT Presentation

This general phenomenon known as concurrency shows up at many different levels of a computer system Hard ware exception handlers processes and Unix signal handlers ar e all familiar examples Thus far we have treated concurrency mainly as a mechanis ID: 69980

This general phenomenon known

Share:

Link:

Embed:

Download Presentation from below link

Download Pdf The PPT/PDF document "Chapter Concurrent Programming As we le..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Chapter12ConcurrentProgrammingAswelearnedinChapter8,logicalcontrolowsareconcurrentiftheyoverlapintime.Thisgeneralphenomenon,knownasconcurrency,showsupatmanydifferentlevelsofacomputersystem.Hardwareexceptionhandlers,processes,andUnixsignalhandlersareallfamiliarexamples.Thusfar,wehavetreatedconcurrencymainlyasamechanismthattheoperatingsystemkernelusestorunmultipleapplicationprograms.Butconcurrencyisnotjustlimitedtothekernel.Itcanplayanimportantroleinapplicationprogramsaswell.Forexample,wehaveseenhowUnixsignalhandlersallowapplicationstorespondtoasynchronouseventssuchastheusertypingctrl-cortheprogramaccessinganundenedareaofvirtualmemory.Application-levelconcurrencyisusefulinotherwaysaswell:AccessingslowI/Odevices.WhenanapplicationiswaitingfordatatoarrivefromaslowI/Odevicesuchasadisk,thekernelkeepstheCPUbusybyrunningotherprocesses.IndividualapplicationscanexploitconcurrencyinasimilarwaybyoverlappingusefulworkwithI/Orequests.Interactingwithhumans.Peoplewhointeractwithcomputersdemandtheabilitytoperformmultipletasksatthesametime.Forexample,theymightwanttoresizeawindowwhiletheyareprintingadocument.Modernwindowingsystemsuseconcurrencytoprovidethiscapability.Eachtimetheuserrequestssomeaction(say,byclickingthemouse),aseparateconcurrentlogicalowiscreatedtoperformtheaction.Reducinglatencybydeferringwork.Sometimes,applicationscanuseconcurrencytoreducethelatencyofcertainoperationsbydeferringotheroperationsandperformingthemconcurrently.Forexample,adynamicstorageallocatormightreducethelatencyofindividualfreeoperationsbydeferringcoalescingtoaconcurrent“coalescing”owthatrunsatalowerpriority,soakingupspareCPUcyclesastheybecomeavailable.Servicingmultiplenetworkclients.TheiterativenetworkserversthatwestudiedinChapter11areunrealisticbecausetheycanonlyserviceoneclientatatime.Thus,asingleslowclientcandenyservicetoeveryotherclient.Forarealserverthatmightbeexpectedtoservicehundredsorthousandsofclientspersecond,itisnotacceptabletoallowoneslowclienttodenyservicetotheothers.Abetterapproachistobuildaconcurrentserverthatcreatesaseparatelogicalowforeachclient.Thisallows895 896CHAPTER12.CONCURRENTPROGRAMMINGtheservertoservicemultipleclientsconcurrently,andprecludesslowclientsfrommonopolizingtheserver.Computinginparallelonmulti-coremachines.Manymodernsystemsareequippedwithmulti-coreprocessorsthatcontainmultipleCPUs.Applicationsthatarepartitionedintoconcurrentowsoftenrunfasteronmulti-coremachinesthanonuniprocessormachinesbecausetheowsexecuteinparallelratherthanbeinginterleaved.Applicationsthatuseapplication-levelconcurrencyareknownasconcurrentprograms.Modernoperatingsystemsprovidethreebasicapproachesforbuildingconcurrentprograms:Processes.Withthisapproach,eachlogicalcontrolowisaprocessthatisscheduledandmaintainedbythekernel.Sinceprocesseshaveseparatevirtualaddressspaces,owsthatwanttocommunicatewitheachothermustusesomekindofexplicitinterprocesscommunication(IPC)mechanism.I/Omultiplexing.Thisisaformofconcurrentprogrammingwhereapplicationsexplicitlyscheduletheirownlogicalowsinthecontextofasingleprocess.Logicalowsaremodeledasstatemachinesthatthemainprogramexplicitlytransitionsfromstatetostateasaresultofdataarrivingonledescriptors.Sincetheprogramisasingleprocess,allowssharethesameaddressspace.Threads.Threadsarelogicalowsthatruninthecontextofasingleprocessandarescheduledbythekernel.Youcanthinkofthreadsasahybridoftheothertwoapproaches,scheduledbythekernellikeprocessows,andsharingthesamevirtualaddressspacelikeI/Omultiplexingows.Thischapterinvestigatesthesethreedifferentconcurrentprogrammingtechniques.Tokeepourdiscus-sionconcrete,wewillworkwiththesamemotivatingapplicationthroughout–aconcurrentversionoftheiterativeechoserverfromSection11.4.9.12.1ConcurrentProgrammingWithProcessesThesimplestwaytobuildaconcurrentprogramiswithprocesses,usingfamiliarfunctionssuchasfork,exec,andwaitpid.Forexample,anaturalapproachforbuildingaconcurrentserveristoacceptclientconnectionrequestsintheparent,andthencreateanewchildprocesstoserviceeachnewclient.Toseehowthismightwork,supposewehavetwoclientsandaserverthatislisteningforconnectionrequestsonalisteningdescriptor(say,3).Nowsupposethattheserveracceptsaconnectionrequestfromclient1andreturnsaconnecteddescriptor(say,4),asshowninFigure12.1.Afteracceptingtheconnectionrequest,theserverforksachild,whichgetsacompletecopyoftheserver'sdescriptortable.Thechildclosesitscopyoflisteningdescriptor3,andtheparentclosesitscopyofcon-necteddescriptor4,sincetheyarenolongerneeded.ThisgivesusthesituationinFigure12.2,wherethechildprocessisbusyservicingtheclient.Sincetheconnecteddescriptorsintheparentandchildeachpointtothesameletableentry,itiscrucialfortheparenttocloseitscopyoftheconnecteddescriptor.Other-wise,theletableentryforconnecteddescriptor4willneverbereleased,andtheresultingmemoryleakwilleventuallyconsumetheavailablememoryandcrashthesystem. 12.1.CONCURRENTPROGRAMMINGWITHPROCESSES897 Client 2 clientfd Client 1 clientfd Server connfd (4) listenfd (3) Connectionrequest Figure12.1:Step1:Serveracceptsconnectionrequestfromclient. Client 2 clientfd Client 1 clientfd Server listenfd (3) Child 1 connfd (4) Data transfers Figure12.2:Step2:Serverforksachildprocesstoservicetheclient.Nowsupposethataftertheparentcreatesthechildforclient1,itacceptsanewconnectionrequestfromclient2andreturnsanewconnecteddescriptor(say,5),asshowninFigure12.3. Client 2 clientfd Client 1 clientfd Server listenfd (3) Child 1 connfd (4) Connectionrequest connfd (5) Data transfers Figure12.3:Step3:Serveracceptsanotherconnectionrequest.Theparentthenforksanotherchild,whichbeginsservicingitsclientusingconnecteddescriptor5,asshowninFigure12.4.Atthispoint,theparentiswaitingforthenextconnectionrequestandthetwochildrenareservicingtheirrespectiveclientsconcurrently.12.1.1AConcurrentServerBasedonProcessesFigure12.5showsthecodeforaconcurrentechoserverbasedonprocesses.Theechofunctioncalledinline29comesfromFigure11.21.Thereareseveralimportantpointstomakeaboutthisserver:First,serverstypicallyrunforlongperiodsoftime,sowemustincludeaSIGCHLDhandlerthat 898CHAPTER12.CONCURRENTPROGRAMMING Client 2 clientfd Client 1 clientfd Server listenfd (3) Child 1 connfd (4) Data transfers Child 2 connfd (5) Data transfers Figure12.4:Step4:Serverforksanotherchildtoservicethenewclient.reapszombiechildren(lines4–9).SinceSIGCHLDsignalsareblockedwhiletheSIGCHLDhandlerisexecuting,andsinceUnixsignalsarenotqueued,theSIGCHLDhandlermustbepreparedtoreapmultiplezombiechildren.Second,theparentandthechildmustclosetheirrespectivecopiesofconnfd(lines33and30,respectively).Aswehavementioned,thisisespeciallyimportantfortheparent,whichmustcloseitscopyoftheconnecteddescriptortoavoidamemoryleak.Finally,becauseofthereferencecountinthesocket'sletableentry,theconnectiontotheclientwillnotbeterminateduntilboththeparent'sandchild'scopiesofconnfdareclosed.12.1.2ProsandConsofProcessesProcesseshaveacleanmodelforsharingstateinformationbetweenparentsandchildren:letablesaresharedanduseraddressspacesarenot.Havingseparateaddressspacesforprocessesisbothanadvantageandadisadvantage.Itisimpossibleforoneprocesstoaccidentallyoverwritethevirtualmemoryofanotherprocess,whicheliminatesalotofconfusingfailures–anobviousadvantage.Ontheotherhand,separateaddressspacesmakeitmoredifcultforprocessestosharestateinformation.Toshareinformation,theymustuseexplicitIPC(interprocesscommunications)mechanisms.(SeeAside.)Anotherdisadvantageofprocess-baseddesignsisthattheytendtobeslowerbecausetheoverheadforprocesscontrolandIPCishigh.Aside:UnixIPCYouhavealreadyencounteredseveralexamplesofIPCinthistext.ThewaitpidfunctionandUnixsignalsfromChapter8areprimitiveIPCmechanismsthatallowprocessestosendtinymessagestoprocessesrunningonthesamehost.ThesocketsinterfacefromChapter11isanimportantformofIPCthatallowsprocessesondifferenthoststoexchangearbitrarybytestreams.However,thetermUnixIPCistypicallyreservedforahodge-podgeoftechniquesthatallowprocessestocommunicatewithotherprocessesthatarerunningonthesamehost.Examplesincludepipes,FIFOs,SystemVsharedmemory,andSystemVsemaphores.Thesemechanismsarebeyondourscope.ThebookbyStevens[108]isagoodreference.EndAside.PracticeProblem12.1: 12.1.CONCURRENTPROGRAMMINGWITHPROCESSES899 code/conc/echoserverp.c 1 #include"csapp.h" 2 voidecho(intconnfd); 34 voidsigchld_handler(intsig) 5 { 6 while(waitpid(-1,0,WNOHANG)�0) 7 ; 8 return; 9 } 1011 intmain(intargc,char**argv) 12 { 13 intlistenfd,connfd,port; 14 socklen_tclientlen=sizeof(structsockaddr_in); 15 structsockaddr_inclientaddr; 1617 if(argc!=2){ 18 fprintf(stderr,"usage:%sport&#x-2.2;䥢\n",argv[0]); 19 exit(0); 20 } 21 port=atoi(argv[1]); 2223 Signal(SIGCHLD,sigchld_handler); 24 listenfd=Open_listenfd(port); 25 while(1){ 26 connfd=Accept(listenfd,(SA*)&clientaddr,&clientlen); 27 if(Fork()==0){ 28 Close(listenfd);/*Childclosesitslisteningsocket*/ 29 echo(connfd);/*Childservicesclient*/ 30 Close(connfd);/*Childclosesconnectionwithclient*/ 31 exit(0);/*Childexits*/ 32 } 33 Close(connfd);/*Parentclosesconnectedsocket(important!)*/ 34 } 35 } code/conc/echoserverp.cFigure12.5:Concurrentechoserverbasedonprocesses.Theparentforksachildtohandleeachnewconnectionrequest. 900CHAPTER12.CONCURRENTPROGRAMMINGAftertheparentclosestheconnecteddescriptorinline33oftheconcurrentserverinFigure12.5,thechildisstillabletocommunicatewiththeclientusingitscopyofthedescriptor.Why?PracticeProblem12.2:Ifweweretodeleteline30ofFigure12.5,whichclosestheconnecteddescriptor,thecodewouldstillbecorrect,inthesensethattherewouldbenomemoryleak.Why?12.2ConcurrentProgrammingWithI/OMultiplexingSupposeyouareaskedtowriteanechoserverthatcanalsorespondtointeractivecommandsthattheusertypestostandardinput.Inthiscase,theservermustrespondtotwoindependentI/Oevents:(1)anetworkclientmakingaconnectionrequest,and(2)ausertypingacommandlineatthekeyboard.Whicheventdowewaitforrst?Neitheroptionisideal.Ifwearewaitingforaconnectionrequestinaccept,thenwecannotrespondtoinputcommands.Similarly,ifwearewaitingforaninputcommandinread,thenwecannotrespondtoanyconnectionrequests.OnesolutiontothisdilemmaisatechniquecalledI/Omultiplexing.Thebasicideaistousetheselectfunctiontoaskthekerneltosuspendtheprocess,returningcontroltotheapplicationonlyafteroneormoreI/Oeventshaveoccurred,asinthefollowingexamples:Returnwhenanydescriptorinthesetf0;4gisreadyforreading.Returnwhenanydescriptorinthesetf1;2;7gisreadyforwriting.Timeoutif152:13secondshaveelapsedwaitingforanI/Oeventtooccur.Selectisacomplicatedfunctionwithmanydifferentusagescenarios.Wewillonlydiscusstherstscenario:waitingforasetofdescriptorstobereadyforreading.See[109,110]foracompletediscussion. #includeunistd.h&#x-2.2;䥢#includesys/types.h&#x-2.2;䥢intselect(intn,fd set*fdset,NULL,NULL,NULL);Returnsnonzerocountofreadydescriptors,1onerrorFD ZERO(fd set*fdset);/*Clearallbitsinfdset*/FD CLR(intfd,fd set*fdset);/*Clearbitfdinfdset*/FD SET(intfd,fd set*fdset);/*Turnonbitfdinfdset*/FD ISSET(intfd,fd set*fdset);/*Isbitfdinfdsetturnedon?*/Macrosformanipulatingdescriptorsets Theselectfunctionmanipulatessetsoftypefd set,whichareknownasdescriptorsets.Logically,wethinkofadescriptorsetasabitvector(introducedinSection2.1)ofsizen:bn1;:::;b1;b0: 12.2.CONCURRENTPROGRAMMINGWITHI/OMULTIPLEXING901Eachbitbkcorrespondstodescriptork.Descriptorkisamemberofthedescriptorsetifandonlyifbk=1.Youareonlyallowedtodothreethingswithdescriptorsets:(1)allocatethem,(2)assignonevariableofthistypetoanother,and(3)modifyandinspectthemusingtheFD ZERO,FD SET,FD CLR,andFD ISSETmacros.Forourpurposes,theselectfunctiontakestwoinputs:adescriptorset(fdset)calledthereadset,andthecardinality(n)ofthereadset(actuallythemaximumcardinalityofanydescriptorset).Theselectfunctionblocksuntilatleastonedescriptorinthereadsetisreadyforreading.Adescriptorkisreadyforreadingifandonlyifarequesttoread1bytefromthatdescriptorwouldnotblock.Asasideeffect,selectmodiesthefd setpointedtobyargumentfdsettoindicateasubsetofthereadsetcalledthereadyset,consistingofthedescriptorsinthereadsetthatarereadyforreading.Thevaluereturnedbythefunctionindicatesthecardinalityofthereadyset.Notethatbecauseofthesideeffect,wemustupdatethereadseteverytimeselectiscalled.Thebestwaytounderstandselectistostudyaconcreteexample.Figure12.6showshowwemightuseselecttoimplementaniterativeechoserverthatalsoacceptsusercommandsonthestandardinput.Webeginbyusingtheopen listenfdfunctionfromFigure11.17toopenalisteningdescriptor(line17),andthenusingFD ZEROtocreateanemptyreadset(line19):listenfdstdin3210 read set(;): 0 0 0 0 Next,inlines20and21,wedenethereadsettoconsistofdescriptor0(standardinput)anddescriptor3(thelisteningdescriptor),respectively:listenfdstdin3210 read set(f0;3g): 1 0 0 1 Atthispoint,webeginthetypicalserverloop.Butinsteadofwaitingforaconnectionrequestbycallingtheacceptfunction,wecalltheselectfunction,whichblocksuntileitherthelisteningdescriptororstandardinputisreadyforreading(line25).Forexample,hereisthevalueofready setthatselectwouldreturniftheuserhittheenterkey,thuscausingthestandardinputdescriptortobecomereadyforreading:listenfdstdin3210 ready set(f0g): 0 0 0 1 Onceselectreturns,weusetheFD ISSETmacrotodeterminewhichdescriptorsarereadyforreading.Ifstandardinputisready(line26),wecallthecommandfunction,whichreads,parses,andrespondstothecommandbeforereturningtothemainroutine.Ifthelisteningdescriptorisready(line28),wecallaccepttogetaconnecteddescriptor,andthencalltheechofunctionfromFigure11.21,whichechoeseachlinefromtheclientuntiltheclientclosesitsendoftheconnection.Whilethisprogramisagoodexampleofusingselect,itstillleavessomethingtobedesired.Theproblemisthatonceitconnectstoaclient,itcontinuesechoinginputlinesuntiltheclientclosesitsendof 902CHAPTER12.CONCURRENTPROGRAMMING code/conc/select.c 1 #include"csapp.h" 2 voidecho(intconnfd); 3 voidcommand(void); 45 intmain(intargc,char**argv) 6 { 7 intlistenfd,connfd,port; 8 socklen_tclientlen=sizeof(structsockaddr_in); 9 structsockaddr_inclientaddr; 10 fd_setread_set,ready_set; 1112 if(argc!=2){ 13 fprintf(stderr,"usage:%sport&#x-2.2;䥢\n",argv[0]); 14 exit(0); 15 } 16 port=atoi(argv[1]); 17 listenfd=Open_listenfd(port); 1819 FD_ZERO(&read_set);/*Clearreadset*/ 20 FD_SET(STDIN_FILENO,&read_set);/*Addstdintoreadset*/ 21 FD_SET(listenfd,&read_set);/*Addlistenfdtoreadset*/ 2223 while(1){ 24 ready_set=read_set; 25 Select(listenfd+1,&ready_set,NULL,NULL,NULL); 26 if(FD_ISSET(STDIN_FILENO,&ready_set)) 27 command();/*Readcommandlinefromstdin*/ 28 if(FD_ISSET(listenfd,&ready_set)){ 29 connfd=Accept(listenfd,(SA*)&clientaddr,&clientlen); 30 echo(connfd);/*EchoclientinputuntilEOF*/ 31 Close(connfd); 32 } 33 } 34 } 3536 voidcommand(void){ 37 charbuf[MAXLINE]; 38 if(!Fgets(buf,MAXLINE,stdin)) 39 exit(0);/*EOF*/ 40 printf("%s",buf);/*Processtheinputcommand*/ 41 } code/conc/select.cFigure12.6:AniterativeechoserverthatusesI/Omultiplexing.Theserverusesselecttowaitforconnectionrequestsonalisteningdescriptorandcommandsonstandardinput. 12.2.CONCURRENTPROGRAMMINGWITHI/OMULTIPLEXING903theconnection.Thus,ifyoutypeacommandtostandardinput,youwillnotgetaresponseuntiltheserverisnishedwiththeclient.Abetterapproachwouldbetomultiplexatanergranularity,echoing(atmost)onetextlineeachtimethroughtheserverloop.PracticeProblem12.3:InmostUnixsystems,typingctrl-dindicatesEOFonstandardinput.Whathappensifyoutypectrl-dtotheprograminFigure12.6whileitisblockedinthecalltoselect?12.2.1AConcurrentEvent-DrivenServerBasedonI/OMultiplexingI/Omultiplexingcanbeusedasthebasisforconcurrentevent-drivenprograms,whereowsmakeprogressasaresultofcertainevents.Thegeneralideaistomodellogicalowsasstatemachines.Informally,astatemachineisacollectionofstates,inputevents,andtransitionsthatmapstatesandinputeventstostates.Eachtransitionmapsan(inputstate,inputevent)pairtoanoutputstate.Aself-loopisatransitionbetweenthesameinputandoutputstate.Statemachinesaretypicallydrawnasdirectedgraphs,wherenodesrepresentstates,directedarcsrepresenttransitions,andarclabelsrepresentinputevents.Astatemachinebeginsexecutioninsomeinitialstate.Eachinputeventtriggersatransitionfromthecurrentstatetothenextstate.Foreachnewclientk,aconcurrentserverbasedonI/Omultiplexingcreatesanewstatemachineskandassociatesitwithconnecteddescriptordk.AsshowninFigure12.7,eachstatemachineskhasonestate(“waitingfordescriptordktobereadyforreading”),oneinputevent(“descriptordkisreadyforreading”),andonetransition(“readatextlinefromdescriptordk”). Transition: ”read a text line from descriptor dk " State: ”waiting for descriptor dk to be ready for reading” State: ”waiting for descriptor dk to be ready for reading”Input event: ”descriptor dk is ready for reading" Figure12.7:Statemachineforalogicalowinaconcurrentevent-drivenechoserver.TheserverusestheI/Omultiplexing,courtesyoftheselectfunction,todetecttheoccurrenceofinputevents.Aseachconnecteddescriptorbecomesreadyforreading,theserverexecutesthetransitionforthecorrespondingstatemachine,inthiscasereadingandechoingatextlinefromthedescriptor.Figure12.8showsthecompleteexamplecodeforaconcurrentevent-drivenserverbasedonI/Omultiplex-ing.Thesetofactiveclientsismaintainedinapoolstructure(lines3–11).Afterinitializingthepoolbycallinginit pool(line29),theserverentersaninniteloop.Duringeachiterationofthisloop,theservercallstheselectfunctiontodetecttwodifferentkindsofinputevents:(a)aconnectionrequestarrivingfromanewclient,and(b)aconnecteddescriptorforanexistingclientbeingreadyforreading.Whenaconnectionrequestarrives(line36),theserveropenstheconnection(line37)andcallstheadd clientfunctiontoaddtheclienttothepool(line38).Finally,theservercallsthecheck clientsfunctiontoechoasingletextlinefromeachreadyconnecteddescriptor(line42). 904CHAPTER12.CONCURRENTPROGRAMMING code/conc/echoservers.c 1 #include"csapp.h" 23 typedefstruct{/*representsapoolofconnecteddescriptors*/ 4 intmaxfd;/*largestdescriptorinread_set*/ 5 fd_setread_set;/*setofallactivedescriptors*/ 6 fd_setready_set;/*subsetofdescriptorsreadyforreading*/ 7 intnready;/*numberofreadydescriptorsfromselect*/ 8 intmaxi;/*highwaterindexintoclientarray*/ 9 intclientfd[FD_SETSIZE];/*setofactivedescriptors*/ 10 rio_tclientrio[FD_SETSIZE];/*setofactivereadbuffers*/ 11 }pool; 1213 intbyte_cnt=0;/*countstotalbytesreceivedbyserver*/ 1415 intmain(intargc,char**argv) 16 { 17 intlistenfd,connfd,port; 18 socklen_tclientlen=sizeof(structsockaddr_in); 19 structsockaddr_inclientaddr; 20 staticpoolpool; 2122 if(argc!=2){ 23 fprintf(stderr,"usage:%sport&#x-2.2;䥢\n",argv[0]); 24 exit(0); 25 } 26 port=atoi(argv[1]); 2728 listenfd=Open_listenfd(port); 29 init_pool(listenfd,&pool); 30 while(1){ 31 /*Waitforlistening/connecteddescriptor(s)tobecomeready*/ 32 pool.ready_set=pool.read_set; 33 pool.nready=Select(pool.maxfd+1,&pool.ready_set,NULL,NULL,NULL); 3435 /*Iflisteningdescriptorready,addnewclienttopool*/ 36 if(FD_ISSET(listenfd,&pool.ready_set)){ 37 connfd=Accept(listenfd,(SA*)&clientaddr,&clientlen); 38 add_client(connfd,&pool); 39 } 4041 /*Echoatextlinefromeachreadyconnecteddescriptor*/ 42 check_clients(&pool); 43 } 44 } code/conc/echoservers.cFigure12.8:ConcurrentechoserverbasedonI/Omultiplexing.Eachserveriterationechoesatextlinefromeachreadydescriptor. 12.2.CONCURRENTPROGRAMMINGWITHI/OMULTIPLEXING905Theinit poolfunction(Figure12.9)initializestheclientpool.Theclientfdarrayrepresentsasetofconnecteddescriptors,withtheinteger1denotinganavailableslot.Initially,thesetofconnecteddescriptorsisempty(lines5–7),andthelisteningdescriptoristheonlydescriptorintheselectreadset(lines10–12). code/conc/echoservers.c 1 voidinit_pool(intlistenfd,pool*p) 2 { 3 /*Initially,therearenoconnecteddescriptors*/ 4 inti; 5 p-�maxi=-1; 6 for(i=0;iFD_SETSIZE;i++) 7 p-�clientfd[i]=-1; 89 /*Initially,listenfdisonlymemberofselectreadset*/ 10 p-�maxfd=listenfd; 11 FD_ZERO(&p-�read_set); 12 FD_SET(listenfd,&p-�read_set); 13 } code/conc/echoservers.cFigure12.9:init pool:Initializesthepoolofactiveclients.Theadd clientfunction(Figure12.10)addsanewclienttothepoolofactiveclients.Afterndinganemptyslotintheclientfdarray,theserveraddstheconnecteddescriptortothearrayandinitializesacorrespondingRIOreadbuffersothatwecancallrio readlinebonthedescriptor(lines8–9).Wethenaddtheconnecteddescriptortotheselectreadset(line12),andweupdatesomeglobalpropertiesofthepool.Themaxfdvariable(lines15–16)keepstrackofthelargestledescriptorforselect.Themaxivariable(lines17–18)keepstrackofthelargestindexintotheclientfdarraysothatthecheck clientsfunctionsdoesnothavetosearchtheentirearray.Thecheck clientsfunctionechoesatextlinefromeachreadyconnecteddescriptor.Ifwearesuc-cessfulinreadingatextlinefromthedescriptor,thenweechothatlinebacktotheclient(lines15–18).Noticethatinline15wearemaintainingacumulativecountoftotalbytesreceivedfromallclients.IfwedetectEOFbecausetheclienthascloseditsendoftheconnection,thenwecloseourendoftheconnection(line23)andremovethedescriptorfromthepool(lines24–25).IntermsofthenitestatemodelinFigure12.7,theselectfunctiondetectsinputevents,andtheadd clientfunctioncreatesanewlogicalow(statemachine).Thecheck clientsfunctionper-formsstatetransitionsbyechoinginputlines,anditalsodeletesthestatemachinewhentheclienthasnishedsendingtextlines.12.2.2ProsandConsofI/OMultiplexingTheserverinFigure12.8providesaniceexampleoftheadvantagesanddisadvantagesofevent-drivenprogrammingbasedonI/Omultiplexing.Oneadvantageisthatevent-drivendesignsgiveprogrammers 906CHAPTER12.CONCURRENTPROGRAMMING code/conc/echoservers.c 1 voidadd_client(intconnfd,pool*p) 2 { 3 inti; 4 p-�nready--; 5 for(i=0;iFD_SETSIZE;i++)/*Findanavailableslot*/ 6 if(p-�clientfd[i]0){ 7 /*Addconnecteddescriptortothepool*/ 8 p-�clientfd[i]=connfd; 9 Rio_readinitb(&p-�clientrio[i],connfd); 1011 /*Addthedescriptortodescriptorset*/ 12 FD_SET(connfd,&p-�read_set); 1314 /*Updatemaxdescriptorandpoolhighwatermark*/ 15 if(connfd�p-�maxfd) 16 p-�maxfd=connfd; 17 if(i�p-�maxi) 18 p-�maxi=i; 19 break; 20 } 21 if(i==FD_SETSIZE)/*Couldn'tfindanemptyslot*/ 22 app_error("add_clienterror:Toomanyclients"); 23 } code/conc/echoservers.cFigure12.10:add client:Addsanewclientconnectiontothepool. 12.2.CONCURRENTPROGRAMMINGWITHI/OMULTIPLEXING907 code/conc/echoservers.c 1 voidcheck_clients(pool*p) 2 { 3 inti,connfd,n; 4 charbuf[MAXLINE]; 5 rio_trio; 67 for(i=0;(i=p-&#x-2.2;䥢maxi)&&(p-&#x-2.2;䥢nready&#x-2.2;䥢0);i++){ 8 connfd=p-�clientfd[i]; 9 rio=p-�clientrio[i]; 1011 /*Ifthedescriptorisready,echoatextlinefromit*/ 12 if((connfd�0)&&(FD_ISSET(connfd,&p-�ready_set))){ 13 p-�nready--; 14 if((n=Rio_readlineb(&rio,buf,MAXLINE))!=0){ 15 byte_cnt+=n; 16 printf("Serverreceived%d(%dtotal)bytesonfd%d\n", 17 n,byte_cnt,connfd); 18 Rio_writen(connfd,buf,n); 19 } 2021 /*EOFdetected,removedescriptorfrompool*/ 22 else{ 23 Close(connfd); 24 FD_CLR(connfd,&p-�read_set); 25 p-�clientfd[i]=-1; 26 } 27 } 28 } 29 } code/conc/echoservers.cFigure12.11:check clients:Servicesreadyclientconnections. 908CHAPTER12.CONCURRENTPROGRAMMINGmorecontroloverthebehavioroftheirprogramsthanprocess-baseddesigns.Forexample,wecanimaginewritinganevent-drivenconcurrentserverthatgivespreferredservicetosomeclients,whichwouldbedifcultforaconcurrentserverbasedonprocesses.Anotheradvantageisthatanevent-drivenserverbasedonI/Omultiplexingrunsinthecontextofasingleprocess,andthuseverylogicalowhasaccesstotheentireaddressspaceoftheprocess.Thismakesiteasytosharedatabetweenows.Arelatedadvantageofrunningasasingleprocessisthatyoucandebugyourconcurrentserverasyouwouldanysequentialprogram,usingafamiliardebuggingtoolsuchasGDB.Finally,event-drivendesignsareoftensignicantlymoreefcientthanprocess-baseddesignsbecausetheydonotrequireaprocesscontextswitchtoscheduleanewow.Asignicantdisadvantageofevent-drivendesignsiscodingcomplexity.Ourevent-drivenconcurrentechoserverrequiresthreetimesmorecodethantheprocess-basedserver.Unfortunately,thecomplexityincreasesasthegranularityoftheconcurrencydecreases.Bygranularity,wemeanthenumberofinstructionsthateachlogicalowexecutespertimeslice.Forinstance,inourexampleconcurrentserver,thegranularityofconcurrencyisthenumberofinstructionsrequiredtoreadanentiretextline.Aslongassomelogicalowisbusyreadingatextline,nootherlogicalowcanmakeprogress.Thisisneforourexample,butitmakesourevent-driverservervulnerabletoamaliciousclientthatsendsonlyapartialtextlineandthenhalts.Modifyinganevent-drivenservertohandlepartialtextlinesisanontrivialtask,butitishandledcleanlyandautomaticallybyaprocess-baseddesign.Anothersignicantdisadvantageofevent-baseddesignsisthattheycannotfullyutilizemulti-coreprocessors.PracticeProblem12.4:IntheserverinFigure12.8,wearecarefultoreinitializethepool.ready setvariableimmediatelybeforeeverycalltoselect.Why?12.3ConcurrentProgrammingWithThreadsTothispoint,wehavelookedattwoapproachesforcreatingconcurrentlogicalows.Withtherstap-proach,weuseaseparateprocessforeachow.Thekernelscheduleseachprocessautomatically.Eachprocesshasitsownprivateaddressspace,whichmakesitdifcultforowstosharedata.Withthesec-ondapproach,wecreateourownlogicalowsanduseI/Omultiplexingtoexplicitlyscheduletheows.Becausethereisonlyoneprocess,owssharetheentireaddressspace.Thissectionintroducesathirdapproach—basedonthreads—thatisahybridofthesetwo.Athreadisalogicalowthatrunsinthecontextofaprocess.Thusfarinthisbook,ourprogramshaveconsistedofasinglethreadperprocess.Butmodernsystemsalsoallowustowriteprogramsthathavemultiplethreadsrunningconcurrentlyinasingleprocess.Thethreadsarescheduledautomaticallybythekernel.Eachthreadhasitsownthreadcontext,includingauniqueintegerthreadID(TID),stack,stackpointer,programcounter,general-purposeregisters,andconditioncodes.Allthreadsrunninginaprocesssharetheentirevirtualaddressspaceofthatprocess.LogicalowsbasedonthreadscombinequalitiesofowsbasedonprocessesandI/Omultiplexing.Likeprocesses,threadsarescheduledautomaticallybythekernelandareknowntothekernelbyanintegerID.LikeowsbasedonI/Omultiplexing,multiplethreadsruninthecontextofasingleprocess,andthusshare 12.3.CONCURRENTPROGRAMMINGWITHTHREADS909theentirecontentsoftheprocessvirtualaddressspace,includingitscode,data,heap,sharedlibraries,andopenles.12.3.1ThreadExecutionModelTheexecutionmodelformultiplethreadsissimilarinsomewaystotheexecutionmodelformultipleprocesses.ConsidertheexampleinFigure12.12.Eachprocessbeginslifeasasinglethreadcalledthemainthread.Atsomepoint,themainthreadcreatesapeerthread,andfromthispointintimethetwothreadsrunconcurrently.Eventually,controlpassestothepeerthreadviaacontextswitch,becausethemainthreadexecutesaslowsystemcallsuchasreadorsleep,orbecauseitisinterruptedbythesystem'sintervaltimer.Thepeerthreadexecutesforawhilebeforecontrolpassesbacktothemainthread,andsoon. Time Thread 1(main thread)Thread 2(peer thread) Thread context switch Thread context switch Thread context switch Figure12.12:Concurrentthreadexecution.Threadexecutiondiffersfromprocessesinsomeimportantways.Becauseathreadcontextismuchsmallerthanaprocesscontext,athreadcontextswitchisfasterthanaprocesscontextswitch.Anotherdifferenceisthatthreads,unlikeprocesses,arenotorganizedinarigidparent-childhierarchy.Thethreadsassociatedwithaprocessformapoolofpeers,independentofwhichthreadswerecreatedbywhichotherthreads.Themainthreadisdistinguishedfromotherthreadsonlyinthesensethatitisalwaystherstthreadtorunintheprocess.Themainimpactofthisnotionofapoolofpeersisthatathreadcankillanyofitspeers,orwaitforanyofitspeerstoterminate.Further,eachpeercanreadandwritethesameshareddata.12.3.2PosixThreadsPosixthreads(Pthreads)isastandardinterfaceformanipulatingthreadsfromCprograms.Itwasadoptedin1995andisavailableonmostUnixsystems.Pthreadsdenesabout60functionsthatallowprogramstocreate,kill,andreapthreads,tosharedatasafelywithpeerthreads,andtonotifypeersaboutchangesinthesystemstate.Figure12.13showsasimplePthreadsprogram.Themainthreadcreatesapeerthreadandthenwaitsforittoterminate.Thepeerthreadprints“Hello,world!\n”andterminates.Whenthemainthreaddetectsthatthepeerthreadhasterminated,itterminatestheprocessbycallingexit.