drzewo procesów

Zaprojektować drzewo procesów przedstawione na powyższym grafie. Wypisać parametry procesu według szablonu:

P(nr_procesu) ID:(id_procesu) PID:(id_rodzica) OFFSETs:(id_dzieci)

Funkcja fork() tworzy nowy proces poprzez rozwidlenie rodzic i dziecko. Proces dziecko jest dokładną kopią rodzica. Aby kontrolować co wykonujemy w którym procesie pomocne będą nam wartości zwracane przez funkcję pid_t fork(). Funkcja zwraca 3 wartości:

  • -1 – dla rodzica, kiedy tworzenie procesu nie powiedzie się,
  • 0 – dla dziecka
  • id procesu – dla rodzica (liczba naturalna)

Łatwo zauważyć to na poniższym przykładzie:

switch(fork())
{
  case -1:
    //niepowodzenie, zostajemy w rodzicu

  case 0:
    //kod procesu dziecko

  default:
    //kod procesu rodzic
}

W moim programie użyłem nieco innej konstrukcji kodu tworzącego zadane drzewo procesów – użyłem jedynie funkcji warunkowej IF.

if(!(p2=fork())){       //tworzymy proces p2 i zapisujemy jego ID do zmiennej p2
    if(!(p8=fork())){ //tworzymy proces p8 jako dziecko p2 i zapisujemy jego ID do zmiennej p2
        p(8); printf("\n"); } //kod procesu p8
    else{ p(2); printf("%d\n", p8); } //kod procesu p2 (rodzica)
}
else{ ... //kod procesu - rodzica procesu p2

Jak widać w powyższym kodzie użyłem funkcji p(int x). Służy ona do wypisywania na ekran parametrów bieżącego procesu:

void p(int x){ printf("P%d ID:%d PID:%d OFFSETs:",x,getpid(),getppid()); }

Funkcja:

  • getpid() zwraca ID bieżącego procesu,
  • getppid() zwraca ID rodzica bieżącego procesu.

Funkcje wymagają załączenia dwóch bibliotek – sys/types.h oraz unistd.h.

Opierając się na powyższym kodzie tworzenia dziecka p8 dla procesu p2 zbudowałem drzewo procesów odpowiednio zagnieżdżając funkcje fork() w klamrach danego procesu. Poniżej zamieszczam całą zawartość pliku drzewo.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

void p(int x){
printf("P%d ID:%d PID:%d OFFSETs:",x,getpid(),getppid());
}

int main(void){
int p2,p3,p4,p5,p6,p7,p8,p9,p10,p11;
if(!(p2=fork())){
    if(!(p8=fork())){ p(8); printf("\n"); }
    else{ p(2); printf("%d\n", p8); }
}
else{
    if(!(p3=fork())){
        if(!(p5=fork())){
            if(!(p9=fork())){ p(9); printf("\n"); }
            else{ p(5); printf("%d\n",p9); }
        }
        else{
        if(!(p6=fork())){
            if(!(p10=fork())){ p(10); printf("\n"); }
            else{ p(6); printf("%d\n",p10); }
        }
        else{ p(3); printf("%d,%d\n",p5,p6); }
        }
    }
    else{
        if(!(p4=fork())){
            if(!(p7=fork())){ p(7); printf("\n"); }
            else{ p(4); printf("%d\n",p7);  }
        }
    }
if(p2!=0 & p3!=0 & p4!=0){ p(1); printf("%d,%d,%d\n",p2,p3,p4); }
}
sleep(10);
return 0;
}

Wynikiem uruchomienia powyższego programu jest wyświetlenie na ekranie listy procesów, ich nazw, ID, ID rodzica oraz ID dzieci.

P8 ID:32516 PID:32515 OFFSETs:
P2 ID:32515 PID:32514 OFFSETs:32516
P1 ID:32514 PID:31165 OFFSETs:32515,32517,32521
P9 ID:32519 PID:32518 OFFSETs:
P5 ID:32518 PID:32517 OFFSETs:32519
P3 ID:32517 PID:32514 OFFSETs:32518,32520
P7 ID:32523 PID:32521 OFFSETs:
P4 ID:32521 PID:32514 OFFSETs:32523
P10 ID:32522 PID:32520 OFFSETs:
P6 ID:32520 PID:32517 OFFSETs:32522

Dodatkowo na końcu programu wstawiłem funkcję sleep(), aby przedłużyć działanie procesów i uchwycić je za pomocą funkcji pstree -c wyświetlającej drzewo procesów.

pstree drzewo procesów

Pliki programu drzewo:

Przydatne linki: