Управление вилками в C

У меня есть файл C, который выглядит так:

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
int main () 
{ 
    pid_t child_pid; 
    printf ("The PID is %d\n", (int) getpid ()); 
    child_pid = fork (); 
    if (child_pid != 0)
    { 
        printf ("this is the parent process, with PID %d\n", 
        (int)getpid()); 
        printf ("the child's PID is %d\n", (int) child_pid); 
    } 
    else 
        printf ("this is the child process, with PID %d\n", 
        (int)getpid()); 
    return 0; 
} 

Мне нужно изменить его, чтобы создать иерархию, которая выглядит как

parent (0)
  |
  +---> child (1)
  |
  +---> child (2)
          |
          +----> child (3)
          |
          +----> child (4)
                  |
                  +----> child (5)
                  |

В основном древовидная структура, в которой каждый второй дочерний элемент создает двух новых дочерних элементов. Насколько я понимаю, когда я fork() процесс, каждый процесс будет работать одновременно. Кажется, что добавление fork() в оператор if работает и правильно создает процессы от 0 до 2, поскольку только родитель создаст новую вилку. Но я понятия не имею, как сделать разветвление процесса 2, а не 1. Есть идеи?


person pypmannetjies    schedule 06.08.2009    source источник
comment
Рассматривали ли вы пределы этого процесса? Когда это прекратится и почему? Что он сделает с ОС? (В системе, производной от unix, подумайте о том, чтобы прочитать справочную страницу для ulimit.) Просто пытаюсь помочь.   -  person dmckee --- ex-moderator kitten    schedule 06.08.2009


Ответы (4)


Итак, процесс 1 будет создан первой вилкой. Процесс 2 будет создан форком внутри оператора if. Таким образом, чтобы позволить процессу 2 также разветвляться, вы снова разветвляете внутри оператора if, если второе разветвление не вернуло 0.

Иллюстрация:

if(fork) {
    // Inside process 0
    if(fork) {
        // still in process 0
    } else {
        // in process 2
        if(fork) {
          // still in process 2
        } else {
          // in prcess 3
        }
        // and so on
    }
} else {
    // Inside process 1
}
person sepp2k    schedule 06.08.2009

Дети получают копию состояния родителя во время форка.

Таким образом, если у родителя есть счетчик или другое свойство, то дочерние элементы увидят значение во время их разветвления (но не в том случае, если родитель впоследствии изменит его).

person Will    schedule 06.08.2009

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

Имейте в виду, что fork() — относительно дорогая операция, особенно если вы хотите создать много процессов. Доступны более легкие альтернативы vfork и threads, но я не могу судить, соответствуют ли они вашим потребностям.

person Adriaan    schedule 06.08.2009
comment
Любой процесс может разветвляться, даже детский. На самом деле, так пишутся форк-бомбы, когда каждый процесс разветвляет еще два, пока система не будет перегружена. - person paxdiablo; 06.08.2009
comment
Это было просто упражнение - я бы никогда добровольно не сделал что-то настолько странное :) - person pypmannetjies; 06.08.2009

Старый вопрос, но все еще интересный. справочная страница для fork() сообщает нам, что возвращаемое значение:

В случае успеха родительскому процессу возвращается PID дочернего процесса, а дочернему — 0. В случае сбоя в родительском процессе возвращается -1, дочерний процесс не создается, а errno устанавливается соответствующим образом.

Итак, мы знаем, что fork() возвращает 0 дочернему элементу, мы можем использовать это как механизм управления:

int main()
{
   // Here we're in the parent (0) process

   if(fork())  // This starts the chain, only the parent will do this
    if(!fork()) //the child will pass this, the parent will skip it
     for(count = 0; counter < number_of_processes; counter++) //now the 2nd child loops
     {
         if(fork())
             if(!fork());
         else
             break;
     }

Приведем несколько цифр:

//parent (18402)
if(fork()) // spawns 18403, parent 18402 keeps going
  if(!fork()) // spawns 18404, parent 18402 drops to the end of main()
    for(count = 0; count < number_of_processes; conter++) // 18404 enters here
      if(fork())  // 18404 forks 18405 and then goes on
        if(!fork());  // 18404 spawns 18406 before leaving, 18406 restarts the loop
        else
          break; // 18404 breaks out there
      else
          break; //18405 leaves the loop here

Итак, после одной итерации имеем:

  18402
    |
    +---> 18403
    |
    +---> 18404
            |
            +----> 18405
            |
            +----> 18406
                     |

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

person Mike    schedule 03.12.2012