2016-12-29 2 views
0

Я пытаюсь понять, как работает «вилка». Я написал небольшую программу, чтобы понять это, но исполнение кажется мне очень странным. Действительно, «максимальное окончательное» появляется несколько раз, тогда как оно выше функции «вычислять», которая рекурсивно называется. Не могли бы вы объяснить, почему?пытается понять поведение fork() в c

Вот код:

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

ecrire_fils(int nb, char* name) // function to write in a file 
{ 
    ... 
} 

lire_pere(int* j, char* name) // function to read a file 
{ 
    ... 
} 

int max(int * tab, int debut, int fin) // find the max in an array 
{ 
    .. 

} 


int tab[] = {2,4,5,4,1,2,1,2,255,125}; 
int seuil = 3; 
int maximum; 



int compute(int * tab, int debut, int fin); 

int main(){ 

    printf("\n \n maximum final: %d", compute(tab, 0,9)); 

    return 0; 

} 


int compute(int * tab, int debut, int fin) { 

    int pid1, pid2, status; 
    int milieu = (fin + debut) /2; 
    char name1[20] = "fic1_"; 
    char name2[20] = "fic2_"; 
    char buffer[100]; 
    sprintf(buffer, "%d", getpid()); 
    strcat(name1, buffer); 
    strcat(name2, buffer); 

    if (fin - debut <= seuil) // recherche séquentielle du max 
     return max(tab, debut, fin); // on s'arrête là et on renvoit le maximum: on n'écrit pas dans un fichier et aucun fichier ne sera lu 




    pid1 = fork(); 
    if (pid1 == 0) // actions fils1, s'occupe du debut au milieu 
    { 
     maximum = compute(tab, debut, milieu); // on récupère la valeur du max des fils 
     sleep(1); 

     ecrire_fils(maximum, name1); // on écrit cette valeur dans un fichier qui sera lu par le père 

    } 
    else 
    { 
     pid2 = fork(); 
     if (pid2 == 0) // actions fils2, s'occupe du milieu à la fin 
     { 
      maximum = compute(tab, milieu, fin); 
      sleep(1); 
      // on écrit le résultat dans le fichier 
      ecrire_fils(maximum, name2); 


     } 
     else // actions père 
     { 
      int j1 = 0, j2 = 0; 

      waitpid(pid1, &status, 0); 
      lire_pere(&j1, name1); 

      waitpid(pid2, &status, 0); 
      lire_pere(&j2, name2); 

      printf("\n fils1: %d, fils2: %d (début = %d milieu = %d fin =%d)", j1, j2, debut, milieu, fin); 
      sleep(1); 


      if (j1>j2) 
       return j1; 
      return j2; 

     } 

    } 

} 
+0

Поскольку дети, похоже, не уходят, кроме как возвращаясь, каждый из трех процессов должен печатать что-то из печати в основном. Вы не создали MCVE ([MCVE]), потому что в вашем коде есть неполные функции, поэтому трудно понять, что еще собирается kn. –

ответ

0

Сначала есть один процесс выполняется нормально, пока вы не дойдете до вызова вилки. Когда вызывается fork, создается новый новый процесс, который практически идентичен оригинальному процессу, за исключением возвращаемого значения функции fork. Созданный процесс называется дочерним процессом, и, следовательно, процесс, породивший его, называется родительским процессом.

Поскольку вы хотите выполнять разные задачи для каждой ветви вилки, это требует, чтобы вы могли отличить дочерний процесс от родительского процесса. fork возвращает идентификатор процесса (PID) ребенок (вновь созданный процесс) для родительского процесса

+0

Спасибо! Я думал, что сын, созданный вилкой(), содержит только код после функции fork(). Но он также копирует основную функцию? – Sheep

+0

Yah, Он копирует и создает другой процесс. Если вы поймете мой ответ, тогда примите это. –

+0

ОК :). Как сделать, чтобы выполнить основную функцию только один раз? Если я положу это в if, то он будет вызван для каждого «отца», потому что он рекурсивный ... – Sheep

1

MCVE от вашего комментария (с незначительными исправлениями):

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

int main() 
{ 
    printf("\n %d : pouet", getpid()); 
    int pid = fork(); 
    printf("\n %d : plop", getpid()); 
    if (pid >0) 
    printf("\n %d : chouette", getpid()); 
    printf("\n"); 
    return 0; 
} 

родителька печатает pouet и Безразлично» t сбросить буфер (строго говоря, это частично покраснел - вот почему вы видите только одну пустую строку в начале вывода). Ребенок наследует точную копию родителя, включая все, что остается в буфере stdout. Когда приходит время для того, чтобы ребенок печатал, это содержимое также печатается.

Обратите внимание, что если вы измените строки формата от "\n..." до "...\n", пример будет работать как ожидалось.