260 likes | 366 Views
PROCESSPROGRAMMERING. Föreläsning 4 (26.2.2007 ) Innehåll: Förening av dataströmmar IPC: meddelandeköer. Förening av dataströmmar. Systemanrop i UNIX kan delas in i två kategorier: Långsamma systemanrop Kan blockera en process för alltid Övriga systemanrop Blockerar ej
E N D
PROCESSPROGRAMMERING Föreläsning 4 (26.2.2007) Innehåll: Förening av dataströmmar IPC: meddelandeköer Jonny Karlsson 26.2.2007
Förening av dataströmmar Systemanrop i UNIX kan delas in i två kategorier: • Långsamma systemanrop Kan blockera en process för alltid • Övriga systemanrop Blockerar ej Exempel på systemanrop som kan blockera för alltid: • Läsoperationer, om data saknas • Skrivoperation, om data inte kan accepteras • Öppningsoperationer (t.ex. FIFO) Jonny Karlsson 26.2.2007
Förening av dataströmmar Exempel: Läsning av en rörlednings dataström som visas på skärmen while(..) { read(pd[0], buf, sizeof(buf)); printf(”%s”, buf); } Jonny Karlsson 26.2.2007
Förening av dataströmmar Exempel2: Läsning av två rörledningars dataströmmar som förenas och visas på bildskärmen Lösning1: Blockerande I/O multiplexering med systemanropet select() Lösning2: Icke-blockerande I/O multiplexering med signalering Jonny Karlsson 26.2.2007
Blockerande I/O multiplexering Systemanropet select(): #include <sys/types.h> #include <sys/time.h> #include <unistd.h int select(int maxdeskr, fd_set *readDeskrSet, fd_set *writeDeskrSet, fd_set *exceptDeskrSet, struct timeval *tvptr); maxdeskr Det maximala deskriptorvärdet för de deskriptorer som skall ”lyssnas på” + 1 readDeskrSet Pekare på en post innehållande de deskriptorer som skall ”lyssnas på” när man kollar om en deskr. är redo för avläsning. writeDeskrSet Pekare på en post innehållande de deskriptorer som skall ”lyssnas på” när man kollar om en deskr. är redo för skrivning. Jonny Karlsson 26.2.2007
Blockerande I/O multiplexering exeptDeskrSet Pekare på en post innehållande de deskriptorer som skall ”lyssnas på” när man kollar om en deskr. har hamnat i ett undantagstillstånd (t.ex. uppstått ett fel) tvptr En post som definierar den tid select() skall blockera processen och vänta på en aktiv deskriptor innan programmet går vidare struct timeval { long tv_sec; /*sekunder*/ long tv_usec; /*millisekunder*/ } Returnerar Returnerar antalet aktiva deskriptorer (antalet deskriptorer som är redo för läsning/skrivning eller förorsakat ett fel Jonny Karlsson 26.2.2007
Blockerande I/O multiplexering Argumenten som ges till systemanropet select() berättar för kerneln: • vilka deskriptorer vi är intresserade av • vilka tillstånd hos varje deskriptor vi är intresserade av (läsa, skriva, undantag) • Hur länge vi vill vänta (inte alls, en viss tid eller för alltid) När select() returnerar berättar kerneln för oss: • Det totala antalet deskriptorer som är ”klara” • Vilka deskriptorer som är ”klara” för vilket tillstånd (läsa, skriva, undantag) Om select returnerar ett värde > 0 vet vi att en eller flera deskriptorer är ”redo” för ett visst tillsånd och vi kan därefter kalla på lämpligt systemanrop (oftast read eller write) och samtidigt vara säkra på att processen inte blockeras Jonny Karlsson 26.2.2007
Blockerande I/O multiplexering Det finns fyra definierade macron för hantering av fd_set poster: FD_ZERO(fd_set *fdset) Tömmer posten FD_SET(int deskr, fd_set *fdset); Sätter till en deskriptor i posten som skall övervakas FD_CLR(int deskr, fd_set *fdset); Tar bort en deskriptor ur posten FD_ISSET(int deskr, fd_set *fdset); Blir ”true” om deskriptorn man ger som första parameter är ”redo” Jonny Karlsson 26.2.2007
Blockerande I/O multiplexering Principen för användning av fd_set poster och select(): • Deklarera deskriptorer och fd_set poster • Nolla fd_set posterna med FD_ZERO() • Addera alla deskriptorer man vill testa till en fd_set post med FD_SET() • Låt select() vänta på aktiva deskriptorer • Testa vilken deskriptor som blev ”klar” med FD_ISSET() • Läs data från respektive ”klar” deskriptor Första parametern i select() är ett avgränsarvärde som definierar det maximala värdet för en deskriptor som skall övervakas + 1. Exempel 1 Jonny Karlsson 26.2.2007
Icke-blockerande I/O multiplexering med signalering Signaler kan utnyttjas för att uföra asynkron multiplexering av dataströmmar. Behövs två inställningar för varje deskriptor som skall övervakas: • Deskriptorn måste sättas i icke-blockerande läge • Kerneln skall generera signalen SIGPOLL när en deskriptor som övervakas blir ”redo”. Systemanropet fcntl() kan användas för att ändra ”läget” hos en deskriptor fcntl(deskr, F_SETFL, O_NONBLOCK) //hissar flaggen O_NONBLOCK hos //deskriptorn deskr För mera information om systemanropet fcntl, se man-fil. Jonny Karlsson 26.2.2007
Icke-blockerande I/O multiplexering med signalering Systemanropet ioctl() kan användas för att berätta åt kerneln att generera en viss signal vid ett visst tillstånd hos en övervakad deskriptor ioctl(deskr, I_SETSIG, S_RDNORM) //genererar SIGPOLL när en deskriptor är redo //för avläsning För mera information om systemanropet ioctl, se man-fil. När signalen SIGPOLL genererats måste alla övervakade deskriptorer testas (t.ex. läsas med read) eftersom man inte kan veta vilken deskriptor som orskakat SIGPOLL. Eftersom read inte i detta fall får blockera processen om inget data finns att hämta, måste läsdeskriptorn vara i oblockerande läge. SIGPOLL signalen måste fångas upp, annars avbryts programmet när den första deskriptorn blir aktiv Jonny Karlsson 26.2.2007
Icke-blockerande I/O multiplexering med signalering Systemanropet pause() används för att frysa processen tills en eller flera deskriptorer blir aktiva. Principen för asynkron multiplexering: • Deklarera och skapa deskriptorerna • Definiera en signaluppfångare för signalen SIGPOLL • Ställ in deskriptorerna i icke-blockerande läga • Aktivera signalen SIGPOLL för varje aktiv deskriptor • Vänta på signalen (som informerar om att en deskriptor blivit aktiv) med pause() • Testa varje deskriptor genom att försöka läsa ur dem. Exempel 2 Jonny Karlsson 26.2.2007
IPC IPC = Inter Process Communication En samling systemanrop för processkommunikation Innehåller tre slags kommunikationsverktyg: • Meddelande köer ”message queue” • Delat minne ”shared memory” • Semaforer ”semaphores” Jonny Karlsson 26.2.2007
Meddelandeköer En meddelandekö är en länkad lista som kan bestå av ett visst antal meddelanden. Meddelanden som sätts in i en meddelandekö sparas i datorns minne och Kerneln sköter om köhanteringen. Ett meddelande som finns i en meddelandkö bör ha tre egenskaper: • Data • En längd • Ett typ-värde En meddelandekö avviker från algoritmen för en vanlig kö eftersom man nödvändigtvis inte måste avhämta data från ena ändan av kön. Man kan istället hämta ett meddelande på basen av meddelandets typ Jonny Karlsson 26.2.2007
Meddelandeköer Figur. Exempel på kommunikation mellan två processer via en meddelandkö Jonny Karlsson 26.2.2007
Skapa/ta i bruk en meddelandekö Systemanropet msgget() #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h int msgget(key_t key, int flag); key Ett heltal som karakteriserar en existerande meddelandekö flag Ett heltal som vanligen byggs upp med ”bitwise or”-operatorn: Komponenter: skyddskod|symboliskt ”kommandovärde” 0777|IPC_CREAT Fulla rättigheter och skapar kön om den ej finns, om kön finns tas den existerande kön i bruk. 0777|IPC_EXECL ’’ och skapar kön om dej ej finns. Om kön finns misslyckas msgget() Returnerar ID för meddelandenkön Jonny Karlsson 26.2.2007
Skapa/ta i bruk en meddelandekö Ex. Två processer om skapar och tar i bruk en och samma meddelandekö. Ena processen skapar (Den som exekveras först) och den andra tar i bruk. Jonny Karlsson 26.2.2007
Skicka data till en meddelandekö #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int koID, const void *msgptr, size_t msgsize, int flag); koID Meddelandeköns ID msgptr En pekare på en post innehållande data och meddelandetyp () msgsize Anger meddelandets längd i byte flag Heltal som definierar åtgärd ifall meddelandet inte ryms i kön: flag = 0 Väntar till det finns plats i kön flag = IPC_NOWAIT msgsnd() misslyckas Returnerar 0 vid framgång -1 vid misslyckande Jonny Karlsson 26.2.2007
Skicka data till en meddelandekö Andra parametern i msgsnd() är en pekare på en post som bör vara av följande typ: struct meddelandeformat { long mdlTyp; char text[size]; }; mdlTyp Ett heltalsvärde > 0 som definierar meddelandets typ text Meddelandet som en teckensträng Jonny Karlsson 26.2.2007
Skicka data till en meddelandekö Ex. Skickar ett meddelande av typ 1 innehållande en teckensträng till en meddelandkö med ID=koID. Processen väntar tills meddelandet får plats i kön. Jonny Karlsson 26.2.2007
Ta emot data från en meddelandekö #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgrcv(int koID, const void *msgptr, size_t maxsize, long msgtyp, int flag); koID Meddelandeköns ID msgptr En pekare på en post innehållande data och meddelandetyp maxsize Mottagna meddelandets maximala längd msgtyp Betecknar typen på det meddelande som skall tas emot: msgtyp = 0 Tar emot första meddelandet i kön msgtyp > 0 Tar emot ett meddelande med angiven typ som är först i kön msgtyp < 0 Tar emot första meddelandet med minsta typ- värde eller lika med det absoluta typ-värdet Jonny Karlsson 26.2.2007
Ta emot data från en meddelandekö flag Definierar ågärd ifall kön är tom eller meddelandets längd > maxsize: 0 Blir och vänta på ett meddelande av rätt typ, msgrcv() misslyckas om meddelandets längd > maxsize IPC_NOWAIT msgrcv() misslyckas om data med rätt typ inte finns att hämta i kön MSG_NOERROR Ett överlångt meddelande förkortas till maxsize Jonny Karlsson 26.2.2007
Ta emot data från en meddelandekö Ex. Tar emot första meddelandet av typ 1 från en meddelandkö med ID=koID. Om inget meddelande av typ 1 finns att hämta ur meddelandkön misslyckas msgrcv (returnerar -1) Jonny Karlsson 26.2.2007
Hantering av en meddelandekö Varje meddelandkö är associerad med struktur (struct) som definierar meddelandköns egenskaper: struct msqid_ds { struct ipc_perm msg_perm; //IPC-rättigheter struct msg *msg_first; //Pekare på första msg struct msg *msg_last; //Pekare på sista msg ulong msg_cbytes; //Köstorlek (bytes) ulong msg_qnum; //Antal msg i kön ulong msg_qbytes; //Maximal köstorlek pid_t msg_lspid; //Senaste msgsnd() PID pid_t msg_lrpid; //Senaste msgrcv() PID time_t msg_stime; //Senaste msgsnd() tid time_t msg_rtime; //Senaste msgrcv() tid time_t msg_ctime; //Senaste ändring (tid) } Jonny Karlsson 26.2.2007
Hantering av en meddelandekö #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgctl(int koID, int cmd, struct msqid_ds *buf); koID Meddelandköns ID cmd Ett heltal som definierar hanteringens åtgärd: cmd = IPC_RMID Meddelandkön raderas (buf saknar här bet.) cmd = IPC_STAT Meddelandköns statusinfo kopieras till fältena i den post som utpekas av buf cmd = IPC_SET Meddelandköns status ställs in enligt fältena i den post som buf adresserar buf Pekare på en post av typ struct_msqid_ds Jonny Karlsson 26.2.2007
Hantering av en meddelandekö Ex. Skriver ut på skärmen antalet meddelanden som finns i meddelandkön med ID=koID Jonny Karlsson 26.2.2007