PROCESSPROGRAMMERING Föreläsning 6 (19.3.2007) Innehåll: -Producent – konsument problemet -Förmedling av fildeskriptorer Jonny Karlsson 19.3.2007 En producent och en konsument Konsumenten måste kunna konsumera alla tal som producerats av producenten även om produktionen går snabbare än konsumtionen. Lösning: användning av semaforer (utan semaforskydd skrivs minnesbufferns poster över innan konsumenten hinner läsa alla poster. Jonny Karlsson 19.3.2007 En producent och en konsument Det behövs 2 heltalssemaforer • TOM initialiseras till N=antalet platser i buffern • FULL initialiseras till 0 Pseudokod för producentprocessen: /* delat minne */ int buffer[N], in=0, ut=0; /*semaforer*/ initsemaphore TOM = N; initsemaphore FULL = 0; while(1) { producera(tal); P(TOM); buffer[in] = tal; in = (in + 1) % N; V(FULL); } Jonny Karlsson 19.3.2007 En producent och en konsument Pseudokod för konsumentprocessen: while(1) { P(FULL); tal = buffer[ut]; ut = (ut + 1)%N; V(TOM); } Jonny Karlsson 19.3.2007 Flera konsumenter och producenter Problem: Alla producenter använder samma index-variabel för att placera heltal i kön. Alla konsumenter använder samma index-variabel för att hämta heltal från kön. Lösning: Använd en binär semafor för att kontrollera att endast en producent kommer åt kön/minnesbuffern på en samtidigt. Använd likaså en binär semafor för att kontrollera att endast en konsument får läsa värden ur kön samtidigt. Jonny Karlsson 19.3.2007 Flera konsumenter och producenter Pseudokod för producent-processerna: /* delat minne */ int buffer[N],in=0,ut=0; /* 4 semaforer /* initsemaphore TOM=N; initsemaphore FULL=0; initsemaphore SEMIN=1; initsemaphore SEMUT=1; while(1) { producera(tal); P(TOM); P(SEMIN); buffer[in]=tal; in=(in+1)%N; V(SEMIN); V(FULL); } Jonny Karlsson 19.3.2007 Flera konsumenter och producenter Pseudokod för producent-processerna: while(1) { P(FULL); P(SEMUT); tal = buffer[ut]; ut=(ut+1)%N; V(SEMUT); V(tom); konsumera(tal); } För mer detaljerad beskrivning av konsument-producent probemet se föreläsningskompendium sid 29-31 Jonny Karlsson 19.3.2007 Förmedling av fildeskriptorer En process skapar en fildeskriptor och den öppna fildeskriptorn skickas över till en/flera andra processer. Mycket användbart vid programmering av klient-server applikationer. Mycket typiskt går det till så att serverprocessen gör allt som behövs för att öppna en fil och sedan skickas den öppna fildeskriptorn över till anropande klientprocesser. Jonny Karlsson 19.3.2007 Filhantering Kerneln använder 3 datastrukturer för filhantering och relationerna mellan dessa bestämmer hurdan effekt en process har på en annan vid delning av öppna fildeskriptorer: •Processtabell (process table) •Filtabell (file table) •v-nod tabell (v-node table) Varje process är associerad med en processtabell vilken innehåller en tabell med öppna fildeskriptorer för varje process. Associerade med varje fildeskriptor är: •Flaggor för fildeskriptorerna •En pekare till en filtabell Kerneln uppehåller en filtabell för alla öppna filer. Varje filtabell innehåller: •Filstatusflaggan för filen (read, write, append, nonblocking, m.m.) •Nuvarande ”file offset” (bestämmer var följande read/write operation startar) •En pekare på v-nod tabellen för filen Jonny Karlsson 19.3.2007 Filhantering Varje öppen fil har en v-nod tabell. V-noden innehåller information om filtypen och pekare på funktioner som hanterar filen. V-nod tabellen innehåller även I-nod information vilket berättar bl.a. filägaren och filstorleken. Jonny Karlsson 19.3.2007 Fildelning Två processer delar en öppen fil genom att använda två sparata filtabeller (båda processerna skapar en egen fildeskriptor med open()) Jonny Karlsson 19.3.2007 Fildelning Två processer delar en öppen fil genom att den ena processen skapar fildeskriptorn och överför denna till den andra processen Jonny Karlsson 19.3.2007 Överföring av fildeskriptorer Det man egentligen vill åstadkomma vid överföring av fildeskriptorer är att två eller flere processer delar samma filtabell. Det som egentligen sker tekniskt är att man överför en pekare till en filtabell från en process till en annan. Dena pekare får första tillgängliga deskriptorvärde. Observera att båda processerna har inte samma deskriptornummer eftersom de fortfarande har skilda processtabeller. Om ena processen stänger sin fildeskripor är filen ändå fortfarande öppen för den andra processen. Jonny Karlsson 19.3.2007 Att sända en fildeskriptor En fildeskriptor kan sändas över till en annan process genom en rörledning genom att använda ioctl() funktionen: ioctl(pd[1], I_SENDFD, deskr); pd[1] Deskriptorn för skrivändan i den rörledning genom vilken deskriptorn skall skickas. I_SENDFD Kommandoflagga som berättar att en deskriptor skall skickas. deskr Den fildeskriptor som skall skickas. Jonny Karlsson 19.3.2007 Att ta emot en fildeskriptor En fildeskriptor kan tas emot från en annan process från en rörledning genom att använda ioctl() funktionen: ioctl(pd[1], I_RECVFD, &deskrpek); pd[0] Deskriptorn för läsändan i den rörledning varifrån deskriptorn skall tas emot. I_RECVFD Kommandoflagga som berättar att en deskriptor skall skickas. deskrpek En pekare på en post av typen struct strrecvfd (Se nästa slide) Jonny Karlsson 19.3.2007 Att ta emot en fildeskriptor struct strrecvfd { int fd; uid_t uid; gid_t gid; char fill[8]; } //den nya deskriptorn //användar ID för avsändaren //grupp ID för avsändaren Jonny Karlsson 19.3.2007