Jonny Karlsson PROCESSPROGRAMMERING Föreläsning 6 ( ) Innehåll: -Producent – konsument problemet -Förmedling av fildeskriptorer
Jonny Karlsson 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 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); producera(tal); P(TOM); P(TOM); buffer[in] = tal; buffer[in] = tal; in = (in + 1) % N; in = (in + 1) % N; V(FULL); V(FULL);}
Jonny Karlsson En producent och en konsument while(1){ P(FULL); P(FULL); tal = buffer[ut]; tal = buffer[ut]; ut = (ut + 1)%N; ut = (ut + 1)%N; V(TOM); V(TOM);} Pseudokod för konsumentprocessen:
Jonny Karlsson 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 Flera konsumenter och producenter /* 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); } Pseudokod för producent-processerna:
Jonny Karlsson Flera konsumenter och producenter while(1) { P(FULL); P(SEMUT); tal = buffer[ut]; ut=(ut+1)%N; V(SEMUT); V(tom); konsumera(tal); } Pseudokod för producent-processerna: För mer detaljerad beskrivning av konsument-producent probemet se föreläsningskompendium sid 29-31
Jonny Karlsson 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 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 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 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 Fildelning Två processer delar en öppen fil genom att den ena processen skapar fildeskriptorn och överför denna till den andra processen
Jonny Karlsson Ö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 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_SENDFDKommandoflagga som berättar att en deskriptor skall skickas. deskrDen fildeskriptor som skall skickas.
Jonny Karlsson 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_RECVFDKommandoflagga som berättar att en deskriptor skall skickas. deskrpekEn pekare på en post av typen struct strrecvfd (Se nästa slide)
Jonny Karlsson Att ta emot en fildeskriptor struct strrecvfd { int fd;//den nya deskriptorn uid_t uid;//användar ID för avsändaren gid_t gid;//grupp ID för avsändaren char fill[8]; }