Linuxiarze.pl Forum

Oprogramowanie => Inne => Wątek zaczęty przez: rarha_eu w Styczeń 08, 2019, 06:01:11 PM

Tytuł: Podstawy programowania C, Linux
Wiadomość wysłana przez: rarha_eu w Styczeń 08, 2019, 06:01:11 PM
Witam, mam problem z następującym zadaniem:
"Opracować zestaw programów typu producent-konsument realizujących przy wykorzystaniu
mechanizmu łączy komunikacyjnych (pipes) nastepujący schemat komunikacji międzyprocesowej:
Proces 1:
   czyta dane (pojedyncze wiersze) ze stdin lub pliku i przekazuje je w niezmienionej
   postaci do procesu 2
Proces 2:
   pobiera dane przesłane przez proces 1, Oblicza ilość znaków w każdej linii i
   wyznaczona liczbę przekazuje do procesu 3.
Proces 3:
   Pobiera dane wyprodukowane przez proces 2 i umieszcza je na stdout. Każda odebrana
   jednostka danych powinna zostać wyprowadzona w osobnym wierszu.

Należy zaproponować i zaimplementować mechanizm informowania się procesów o swoim stanie.
Należy wykorzystać do tego dostępny mechanizm sygnałów i kolejek komunikatów. Scenariusz
powiadamiana się procesów o swoim stanie wygląda następująco: do procesu 2 wysyłane są
sygnały. Proces 2 przesyła otrzymany sygnał do procesu macierzystego. Proces macierzysty
zapisuje wartość sygnału do kolejek komunikatów oraz wysyła powiadomienie do procesu 1
o odczytaniu zawartości kolejki komunikatów. Proces 1 po odczytaniu sygnału wysyła
powiadomienie do procesu 2 o odczytanie kolejki komunikatów. Proces 2 powiadamia proces 3
o konieczności odczytu kolejki komunikatów. Wszystkie 3 procesy powinny być powoływane
automatycznie z jednego procesu inicjującego."

Czy ktoś rozumie o co tu chodzi? Bo nie rozumiem koncepcji użycia zarówno potoków jak i kolejek komunikatów (do przesyłania wartości sygnału???) Czy nie wystarczy "z grubsza" użyć popen() i ewentualnie jakiegoś signal handlera żeby program wiedział kiedy czytać dane?
Tytuł: Odp: Podstawy programowania C, Linux
Wiadomość wysłana przez: lesio w Styczeń 08, 2019, 07:31:47 PM
Z tego, co pamiętam, to masz rację. Co prawda już dość dawno pisałem programy wykorzystujące potoki nazwane (czyli fizyczne pliki typu pipe). ale pamiętam na 100%, że nie musiałem stosować żadnych sygnałów. Na potoku "siedziały" jednocześnie obydwa procesy (nadawczy i odbiorczy) i odbiorczy czekał na instrukcji wczytywania, aż pojawi się dana do wczytania. Czekał tak długo, ile trzeba było. Użycie sygnałów niepotrzebnie komplikuje sprawę (proces musiałby "wisieć" na jakiejś instrukcji "nic nie robienia" i być z niej budzony przez sygnał - więc lepiej niech sobie "wisi" na instrukcji wczytywania danych z potoku).
UWAGA! Ja wykorzystywałem potoki nazwane (czyli pliki typu "pipe"), ponieważ komunikowały się ze sobą  procesy nie mające wspólnego procesu macierzystego. Nie pamiętam, jak zachowują się potoki utworzone w pamięci przy pomocy instrukcji "pipe". Piszę o tym w kontekście nazewnictwa prezentowanego tutaj:
https://pl.wikipedia.org/wiki/Potok_(Unix)
Tytuł: Odp: Podstawy programowania C, Linux
Wiadomość wysłana przez: rarha_eu w Styczeń 08, 2019, 08:09:39 PM
Dzięki wielkie! Masz rację z tym że procesy "wiszą" i czekają na dane z potoku. I rozumiem też koncepcję "komplikowania" poprzez wybudzanie procesu przez sygnał. Jednak z powyższego polecenia wynika że oprócz wybudzania procesu z pętli "nic nie robienia", zastosowane są kolejki komunikatów. Załóżmy że w celu ćwiczenia prowadzący specjalnie skomplikował zadanie. Jednak dalej niejasne jest dla mnie przesyłanie "wartości sygnału" poprzez kolejkę komunikatów. Czym jest "powiadomienie" kiedy procesy de facto 'połączone' są potokiem, kolejką komunikatów, oraz możliwością wysyłania sobie sygnałów? Jeżeli jednak zinterpretujemy to tak jak jest napisane (nawet jeżeli to zbędna komplikacja), to te tzw "powiadomienia", nie mają żadnego wpływu na przebieg programu, bo i tak polega na przekazywaniu danych Proces1->Proces2->Proces3 (oraz ewentualna ich modyfikacja). Czyli mam zaimplementować kolejki komunikatów i sygnały które nic nie zmieniają?
Tytuł: Odp: Podstawy programowania C, Linux
Wiadomość wysłana przez: hobbysta w Styczeń 08, 2019, 10:03:08 PM
Poszukalem w necie - zadanie trudne - ale ciekawe. To jest symulacja rozwiazania w powloce

$ while read FOO; do echo "$FOO" | wc -c ; done

W zadaniu ja rozumiem chodzi z grubsza o cos takiego

$ ls -F | grep /$ | sort

tzn. trzy procesy polaczone kolejkami w cos co nazywa sie 'pipeline' = rurociag byloby po polsku. Kreseczki | to tzw. anonimowe kolejki. Tu jest podobny przyklad z neta

$  who | cut -f1 -d' ' | uniq

rowniez trzy procesy polaczone w rurociag. W rzeczy samej w twoim zadaniu wlasnie chodzi o utworzenie takiego rurociagu. Tu jest strona na ktorej znalazlem kod w C, ktory to realizuje

https://www.softprayog.in/programming/interprocess-communication-using-pipes-in-linux

jest to w zasadzie gotowy szkielet programu, z tym ze wywolanie systemowe execlp trzeba zastapic odpowiednim kodem w C, funkcjami, ktore beda realizowac odpowiednie zadania. To jakby jest czesc pierwsza. Nastepna to komunikacja miedzy tymi procesami - ktora ma byc realizowna tak jak opisane w tresci zadania - sygnaly oraz kolejki komunikatow.

Czyli to jest jakby tak: proces macierzysty tworzy te trzy procesy potomne, laczy je w jeden rurociag - syganly i komunikacja sa potrzebne do synchronizacji - poniewaz procesy dzialaja wspolbieznie. Wiec jakos sie musza dogadac ze soba, co ktory  z nich ma w danej chwili robic. Bez synchronizacji taki rurociag moglby wogole nie zadzialac.

Trzeba  tylko pamietac o roznicy pomiedzy anonimowymi i nazwanymi kolejkami, np.

$ mkfifo ula
$ ls -l ula
prw-r--r-- 1 piotr users 0 Jan  8 21:59 ula

literka p na poczatku wlasnie, informuje, ze ula to nazwana kolejka - p jak 'pipe'. Polecenie mkfifo pozwala uzytkownikowi jawnie utworzyc nazwana kolejke.

Tytuł: Odp: Podstawy programowania C, Linux
Wiadomość wysłana przez: lesio w Styczeń 08, 2019, 10:36:18 PM
ad. rarha_eu
Nie sądzę, by sygnały miały być przesyłane przy użyciu potoków (chociaż oczywiście mogą), ale po prostu jako sygnały:
https://en.wikipedia.org/wiki/C_signal_handling
https://www.gnu.org/software/libc/manual/html_node/Signaling-Another-Process.html
Rozumiem to tak, że proces sobie "śpi" na jakimś poleceniu (typu sleep 99999 w nieskończonej pętli) i otrzymując określony sygnał, przerywa "sen" i wskakuje do procedury odbioru komunikatu z potoku.

ad. hobbysta
fajne konkretne rozwiązanie (bez sygnałów)