Powrót na stronę UNIX

Napisz program realizujacy problem "duży producent-konsumeci". Proces główny najpierw tworzy k procesów potomnych będących konsumentami, a następnie zaczyna pełnić rolę producenta.

Producent wczytuje do swojego lokalnego bufora dane z pliku wejściowego (porcjami po n bajtów, z wyjątkiem ostaneij porcji, która może być mniejsza), wypisuje wczytaną porcję na stdout w formacie "[wyprodukowano] dane [koniec]" i jeśli bufor w pamięci dzielonej jest pusty lub całkowicie skonsumowany, umieszcza te dane w buforze. Następnie informuje konsumentów o nowej dostawie danych.

Konsument w pętli próbuje skonsumować jeden bajt wyprodukowanych danych. Jeśli w buforze jest conajmniej jeden nieskonsumowany bajt, konsument kopiuje jego zawartość do swojej zmiennej lokalnej i za pomocą operacji na semaforze informuje producenta o zwolnieniu jednego bajta w buforze. Po skopiowaniu bajta, konsument wypisuje jego zawartość na stdout w formacie "[PID: start konsumpcji]'bajt' \n", następnie zasypia na nie więcej niż jedną sekundę, a po obudzeniu wypisuje na stdout komunikat "[PID: koniec konsumpcji]'bajt' \n" i zaczyna swoje działanie od nowa.

Producent, po osiągnięciu końca pliku wejściowego, czeka aż wszystkie dane zostaną skonumowane po czym kończy procesy konsumentów czekających na semaforach, zwalnia zasoby dzielone i kończy swoją pracę.

Składnia wywołania programu:
prod_cons k n <plik_wejściowy>
W przypadku nieprawidowego wywołania programu, czyli braku któregokolwiek z parametrów, n<=0 lub k<=0 lub braku pliku weściowego, program ma wypisać usage i zakończyć się.

Do rozwiązania problemu są potrzebne dwa semafory normalne (CAN_CONSUME_SEM=0, CAN_PRODUCE_SEM=n) i jeden binarny, zabezpieczający dostęp do indeksu pierwszego nieskonsumowanego bajtu (FIRST_FREE_SEM=1). W sekcji krytycznej można używać jedynie: memcpy, operatora przypisania i operatorów arytmetycznych. Wszelkie inne operacje, a przede wszystkim produkcja i konsumpcja powinny odbywać się poza sekcją krytyczną.

producent konsumenci

while(1){
   local_buffer = produce(n);
   
   PN(CAN_PRODUCE_SEM, n);
      P(FIRST_FREE_SEM);
         first_free = 0;
	 memcpy(shared_buffer, local_buffer, n);
      V(FIRST_FREE_SEM);
   VN(CAN_CONSUME_SEM, n);
}

while(1){
   PN(CAN_CONSUME_SEM, 1);
      P(FIRST_FREE_SEM);
         local_var = shared_buffer[first_free];
	 first_free ++;
      V(FIRST_FREE_SEM);
   VN(CAN_PRODUCE_SEM, 1);

   consume(local_var);
}

Zadanie będzie sprawdzane przez Przeysława Zdroika, należy je wgrać do katalogu /home2/samba/zdroikp/unix

Szczególna uwagę zwracamy na:

Powrót na stronę UNIX