2012-06-06 14 views
17

Zaczynam się uczyć trochę C i podczas badania widelca, czekam na funkcje, które dostałem do nieoczekiwanego wyniku. Przynajmniej dla mnie.Jak używać fork() do tworzenia tylko 2 procesów podrzędnych?

Czy istnieje sposób na utworzenie tylko 2 procesów potomnych od rodzica?

Oto mój kod:

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

int main() 
{ 
    /* Create the pipe */ 
    int fd [2]; 
    pipe(fd); 

    pid_t pid; 
    pid_t pidb; 


    pid = fork(); 
    pidb = fork(); 

    if (pid < 0) 
    { 
     printf ("Fork Failed\n"); 
     return -1; 
    } 
    else if (pid == 0) 
    { 
     //printf("I'm the child\n"); 
    } 
    else 
    { 
     //printf("I'm the parent\n"); 
    } 

    printf("I'm pid %d\n",getpid()); 

    return 0; 
} 

i tu jest moje wyjście:

I'm pid 6763 
I'm pid 6765 
I'm pid 6764 
I'm pid 6766 

Proszę ignorować część rurową, że nie dostał jeszcze tak daleko. Po prostu próbuję utworzyć tylko 2 procesy potomne, więc oczekuję, że 3 "Jestem pid ..." wypisze tylko 1 dla rodzica, na którym będę czekać i 2 procesy potomne, które będą się komunikować przez potok.

Daj mi znać, jeśli zauważysz, gdzie jest mój błąd.

+1

'fork (2)' jest zarówno bardzo proste i jeden z najbardziej niezrozumiany wywołań API w systemie UNIX. Spójrz na "Powiązany" pasek boczny. Czy jest jakiś szczególny powód, dla którego chcesz komunikować się między dwojgiem dzieci, a nie między rodzicem a dzieckiem? – dmckee

+0

Wywołanie fork() dlaczego sprawdzasz pid == 0? Skąd mam wiedzieć, który z nich jest rodzicem, a który jest dzieckiem? – TwilightSparkleTheGeek

+1

@TwilightSparkleTheGeek 'człowiek widelec' stwierdza: WARTOŚĆ ZWRACAJĄCA Po sukcesie, PID procesu potomnego jest zwracany w rodzicu, a 0 jest zwracana w potomku. W przypadku niepowodzenia zwracane jest -1 w obiekcie nadrzędnym, nie jest tworzony proces potomny, a zmienna errno jest ustawiana odpowiednio. – mimoralea

Odpowiedz

30
pid = fork(); #1 
pidb = fork(); #2 

Załóżmy id proces nadrzędny jest 100, pierwszy widelec tworzy inny proces 101. Teraz obie 100 & 101 kontynuować wykonanie po # 1, więc wykonać drugi widelec. pid 100 osiąga # 2 tworząc kolejny proces 102. pid 101 osiąga # 2 tworząc kolejny proces 103. W efekcie kończymy 4 procesy.

Co należy zrobić, to coś takiego.

if(fork()) # parent 
    if(fork()) #parent 
    else # child2 
else #child1 
+3

To na pewno działa. Jednak polecam zamiast tego używać instrukcji switch. Funkcja fork mogłaby zwrócić wartość -1 i możemy obsłużyć ten błąd w przypadku -1 wewnątrz instrukcji switch. – sj755

+0

Myślałem, że rodzic był po oświadczeniu else. Dlaczego rodzic jest w instrukcji if? Jestem zmieszany. – TwilightSparkleTheGeek

+1

Ponieważ fork zwraca 0 na potomku, a nie na rodzica. Na rodzica zwraca PID procesu potomnego, który właśnie utworzyłeś, co jest bardziej przydatne. – mimoralea

3

Gdy instrukcja fork jest wykonywana przez obiekt nadrzędny, proces potomny jest tworzony zgodnie z oczekiwaniami. Można powiedzieć, że proces potomny wykonuje również instrukcję fork, ale zwraca 0, rodzic jednak zwraca pid. Cały kod po wyciągu z widelca jest wykonywany zarówno przez rodzica i dziecko.

W twoim przypadku działo się tak, że pierwsza instrukcja fork stworzyła proces potomny. Obecnie jeden rodzic, P1 i jedno dziecko, C1.

Teraz oba P1 i C1 napotykają drugą instrukcję fork. Rodzic tworzy kolejne dziecko (c2), jak się spodziewasz, ale nawet dziecko, c1 tworzy proces potomny (c3). W efekcie masz P1, C1, C2 i C3, dlatego masz 4 wydrukowane wyciągi.

Dobrym sposobem na przemyślenie tego jest użycie drzew, przy czym każdy węzeł reprezentuje proces, a węzeł główny jest najwyższym obiektem nadrzędnym.

13

Po utworzeniu procesu należy sprawdzić wartość zwracaną. jeśli tego nie zrobisz, drugi proces będzie wykonywany zarówno przez proces macierzysty, jak i proces potomny, więc masz cztery procesy.

jeśli chcesz utworzyć 2 procesów potomnych, tylko:

if (pid = fork()) { 
    if (pid = fork()) { 
     ; 
    } 
} 

Można tworzyć procesy potomne n jak to:

for (i = 0; i < n; ++i) { 
    pid = fork(); 
    if (pid) { 
     continue; 
    } else if (pid == 0) { 
     break; 
    } else { 
     printf("fork error\n"); 
     exit(1); 
    } 
} 
0

można sprawdzić wartość jako if (pid < 0) tworzenie procesu nie powiodło się informuje, że proces potomny nie powiodł się. fork zwraca identyfikator procesu procesu potomnego, jeśli getpid() jest używany z procesu rodzica ss ..

0

Można utworzyć proces potomny w procesie potomnym. W ten sposób możesz mieć 2 kopie oryginalnego procesu nadrzędnego.

int main (void) { 
    pid_t pid, pid2; 
    int status; 

    pid = fork(); 

    if (pid == 0) { //child process 
     pid2 = fork(); 
     int status2; 

     if (pid2 == 0) { //child of child process 
      printf("friends!\n"); 
     } 
     else { 
      printf("my "); 
      fflush(stdout); 
      wait(&status2); 
     } 
    } 
    else { //parent process 
     printf("Hello "); 
     fflush(stdout); 
     wait(&status); 
    } 

    return 0; 
} 

Drukuje następujące:

Hello my friends! 
Powiązane problemy