вилка для петли - PullRequest
       6

вилка для петли

4 голосов
/ 13 февраля 2010

У меня есть сомнения в следующем фрагменте кода и его поведении:

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

#define N 5
#define nt 1

int pm[N][2],pid[N];
int i,j,size;
char s[100];
int count=0;

int main()
{
 for(i=1;i<N;i++)
    {
      printf("\n i=%d",i);

      if(pid[i]=fork() == -1)
        {
          printf("\n fork not wrking");
          exit(1);
        }
      else if(pid[i]>0)
        {
          printf(" \n pid:%3d\n",pid[i]);
        break;
        }

    }
return 0;
}

Сначала я думал, что код вызовет процесс и пропустит цикл. Таким образом,
1 порождает 2 и пропускает.
2 порождает 3 и пропускает
3 порождает 4 и пропускает
4 порождает 5 и пропускает.

Я попытался выполнить этот код и был удивлен ответом, который я получил (для printf i в коде). Вот вывод

 i=1
 i=2
 i=3
 i=2
 i=4
 i=3
 i=3
 i=3
 i=4
 i=4
 i=4
 i=4
 i=4
 i=4
 i=4

Может кто-нибудь, пожалуйста, объясните мне, что здесь происходит. ПРИМЕЧАНИЕ. Я работаю на машине Solaris.

Ответы [ 5 ]

7 голосов
/ 13 февраля 2010

Обновление

Вам не хватает набора скобок в обновленном коде. Это должно быть if ((pid[i] = fork()) == -1) не if (pid[i] = fork() == -1)!

Последний эквивалентен if (pid[i] = (fork() == -1)) из-за правил приоритета. В конечном итоге каждый раз в цикле присваивается значение от 0 до pid[i], поэтому родители думают, что они являются дочерними процессами, и не выходят из цикла.


Я согласен с вашим анализом того, что должно произойти. Родитель должен породить потомка и затем выйти, поэтому каждая распечатка i=n должна отображаться только один раз.

Вы уверены, что ввели его точно так, как указано в вашем вопросе? Я запустил вашу программу (с небольшими изменениями) и получил результат, который вы прогнозировали:

$ cat fork.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define N 5

int main() {
    int pid[N], i;

    for(i=1;i<N;i++) /* What’s the total number of processes? */
    {
    printf("i=%d\n",i); // Output of all the is
    if((pid[i]=fork())==-1) exit(1);
    else if(pid[i] > 0) break;
    }

    return 0;
}
$ gcc -o fork fork.c
$ ./fork
i=1
i=2
$ i=3
i=4

Обратите внимание, что я переместил \n в распечатке до конца. Когда вы помещаете его в начало строки, в результате stdout не сбрасывается, поэтому вы получаете несколько распечаток, когда родительский и дочерний процессы сбрасывают свои выходные буферы. Это может быть причиной вашей проблемы. FWIW на моем Mac я получил каждую распечатку дважды.

1 голос
/ 13 февраля 2010

Выражение

if (pid[i] = fork() == -1) {

не будет делать то, что вы ожидаете. Вы, вероятно, хотели сказать

if ((pid[i] = fork()) == -1) {
1 голос
/ 13 февраля 2010

Fork создает дублированный процесс, содержащий все, что делает родитель, включая дескрипторы файлов и т. Д. Единственное отличие - это возвращаемое значение fork (): родитель видит pid, потомок видит ноль.Первая итерация создает первого потомка.Его копия i также равна 1, как и родительская.Ребенок вырывается из цикла.Когда я запускаю его, я получаю от вас разные результаты:

[wally@zf ~]$ ./a.out
i=1
i=2
i=3
i=4
0 голосов
/ 13 февраля 2010

Какой вкус Unix вы используете. Есть ли вероятность того, что форк не возвращает int?

В этом случае сравнение pid [i]> 0 может завершиться неудачей.

0 голосов
/ 13 февраля 2010

Каждый дочерний процесс продолжает цикл с текущим значением i при порождении. В результате первый процесс печатает i из 1, а затем порождает ребенка. Затем оба из этих процессов печатают i из 2 и порождают потомка, в общей сложности четыре процесса. Все четыре из них печатают i из 3, и каждый порождает новый процесс, и, наконец, все 8 процессов печатают значение 4.

РЕДАКТИРОВАТЬ: Извините, я упустил из виду часть, где родитель должен был выходить из цикла. Что касается того, почему этого не происходит, это может быть потому, что PID хранится как целое число со знаком, но достаточно велико, чтобы передать максимальное значение со знаком, что делает его отрицательным. Это работает, если вы делаете эту замену?

else if(pid[i] > 0) break;

до

else if(pid[i] != 0) break;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...