Fork i generowanie drzewa procesów

0

Mam za zadanie wywołać funkcję fork, wypisać informacje o procesach potomnych i wypisać drzewo utworzonych procesów. Napisałem coś takiego:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

void wypiszInfoOProcesie()
{
        printf("Identyfikator procesu: %d\n", getpid());
        printf("Identyfikator procesu rodzica: %d\n", getppid());
        printf("Identyfikator uzytkownika procesu: %d\n", getuid());
        printf("Identyfikator grupy przypisanej do procesu: %d\n", getgid());
}

int main()
{
        char c;
        char cmd[50];
        const char* czescKomendy = "pstree -p ";
        snprintf(cmd, strlen(czescKomendy)+5+1, "pstree -p %d", pid);
        /* Proces matka */
        puts("Proces matka");
        wypiszInfoOProcesie();
        puts("Procesy potomne");
        for (int i = 0; i < 3; i++) {
                pid = fork();
                if (pid == 0) {
                        /* Funkcja fork zwrocila wartosc 0, a wiec jestesmy w procesie potomnym */
                        wypiszInfoOProcesie();
                }
        }
        //puts(cmd);
        scanf("%c", &c);
        system(cmd);
        return 0;
}

To jest program na studia więc napisałem go po polsku. W każdym razie napisałem go sam, ale o dziwo nie wiem dlaczego działa. O_o Chodzi mi o końcówkę i wypisywanie tego drzewa procesów.
Skoro trzy razy wywołany został fork to mamy 2^3=8 utworzonych procesów przy czym każdy z nich wykonuje dalsze instrukcje. Wystarczy raz podać znak na wejście i program tylko RAZ rysuje drzewo, czyli wykonuje tę funkcję system. Dlaczego zostaje ona wywołana tylko raz skoro te instrukcje wykonuje każdy z procesów?

2

Primo, brakuje Ci wait/obsługi SIGCHLD. Secundo: pytanie brzmi ile procesów ma dostęp do terminala i co się z nimi dzieje kiedy próbują go uzyskać. Google: SIGTTIN, SIGTTOU :)

2

Sorry za posta pod postem: https://linux.die.net/man/3/forkpty (chyba już kiedyś na forum o tym pisałem... pamiętam że byłem wtedy za granicą, czyli to było dobre 4 lata temu albo więcej :P)

EDIT: znalazłem https://4programmers.net/Forum/C_i_C++/263651-bashtelnet_serversystempopen_sesja_basha_z_c++_lub_c?p=1215464#id1215464
2015 ;P

0

Hmm coś mi się wydaję, że to drzewo procesów potomnych można wygenerować w prostszy sposób zamiast wgłębiać się w szczegóły relacji proces->terminal. Jedyne co mi przychodzi do głowy to jakiś licznik procesów. Skoro następuje kopiowanie przestrzeni adresowej za każdym wywołaniem fork to w sumie powinno działać, ale po dodaniu wait do procesów rodziców.
Sprawdzę to jutro

EDIT: Jednak zły pomysł z licznikiem, bo przecież jak będzie wywołanie wracać do procesu rodzica to stan licznika wróci do stanu licznika procesu rodzica :/

0

Ja nie wiem dokładnie jak Ty masz to zrobić ale nie masz jakiegoś IPC użyć? Albo chociaż odpowiednio zbierać i przetwarzać zwrotki z wait?

0

Zadanie z wait i exec jest właśnie osobno. W tym teoretycznie ma wystarczyć jedynie fork. Tzn. nie mieliśmy wskazane, żeby użyć czegoś jeszcze. Spróbuję pokombinować z licznikiem procesów i wait przy czym ten licznik będę pisał do jakiegoś deskryptora plików. Jak nie wyjdzie w ten sposób to zostawię ze scanf.

Dokładna treść jest taka:
Wywołać funkcję fork() 3 razy np. w pętli i wypisać powyższe identyfikatory dla wszystkich procesów potomnych. Na podstawie wyników narysować „drzewo genealogiczne” tworzonych procesów.

Te identyfikatory to pid, ppid, uid i gid, ale są trywialne do wypisania. Jedyny problem to generacja tego drzewa tak, żeby tylko ostatni proces potomny je wypisywał

1

No i problem rozwiązany. Był dość ciekawy w sumie.

Wystarczy raz podać znak na wejście i program tylko RAZ rysuje drzewo, czyli wykonuje tę funkcję system. Dlaczego zostaje ona wywołana tylko raz skoro te instrukcje wykonuje każdy z procesów?

Otóż nie zostaje wykonana tylko raz chociaż tak należałoby przypuszczać po outpucie programu:

https://ibb.co/WvkHGKx

Istnieje 8 procesów, które oczekują na znak. Wiadomo, że mamy tu do czynienia z operacją I/O. W związku z tym po naciśnięciu przycisku jeden z ośmiu procesów otrzymuje na wejście znak i procesor wywłaszczając wątek głównego tego procesu po prostu wykonuje kolejną instrukcję, w tym przypadku system. Na ekranie pojawia się drzewo procesów. Kolejne procesy nadal czekają na znak, ale w terminalu pojawił się już znak zachęty. Dopiero kiedy wyślę 7 znaków do terminala jestem w stanie wykonywać komendy systemowe. :D Okazało się więc, że rzeczywiście wszystkie procesy wykonują swoje instrukcje i oczekują na wejście. Drzewo natomiast rysuje się tylko raz ze względu na dziwną sytuację z pojawieniem się znaku zachęty, której już wyjaśnić niestety na razie nie umiem. Wychodzi na to, że reszta drzew jest rysowana gdzieś w tle.

1 użytkowników online, w tym zalogowanych: 0, gości: 1