2015-05-12 3 views
2

Я ищу функцию, аналогичную CreateProcess, но в Linux. Я провел много исследований и нашел подход "Fork off and die", который использует двойную вилку для запуска дочернего элемента под init. То есть, разрешить ребенку работать независимо от родителя.Создайте независимый процесс в Linux

Поскольку родительский объект должен возвращать информацию о вновь создаваемом дочернем процессе (то есть pid, имя и т. Д.), Мне нужно знать, запущен ли я в состоянии гонки в моем коде. В настоящее время я форк и извлекаю второй вилочный вил через трубы, а затем дождался выхода первой вилки.

int child = 0; 
int fd[2] = { 0, 0 }; 

if (pipe (fd) != 0) 
    return Process(); 

int pid = fork(); 
if (pid < 0) 
    return Process(); 

if (pid == 0) // Child 
{ 
    if (setsid() != -1) 
    { 
     child = fork(); 
     if (child == 0) 
     { 
      umask (0); // Reset umask 
      close (0); // Close stdin 
      close (1); // Close stdout 
      close (2); // Close stderr 

      execvp (...); 
      _exit (0); 
     } 

     // Do I need waitpid (child) here? 
    } 

    // Write the child PID using the pipe 
    write (fd[1], &child, sizeof (child)); 
    _exit (0); 
} 

else // Parent 
{ 
    // Read the child PID using the pipe 
    read (fd[0], &child, sizeof (child)); 

    // Remove zombie process 
    waitpid (pid, nullptr, 0); 

    // Child must finish exec by this point 

    return Process (child); 
     // Also gets name 
} 

Вопросы:

  • Мне нужен второй waitpid ждать ребенка, чтобы закончить ехес ли?
  • Ожидается ли waitpid при вызове exec?
  • Ожидается ли возврат в ожидании, даже если exit или exec были вызваны до waitpid?
+0

Почему вы хотите удвоить? Двойное форкирование выполняется, когда новый процесс не должен быть ребенком исходного процесса, совершенно противоположным тому, что вы хотите сделать. – fuz

+0

Это именно то, что я хочу сделать. Я хочу создать процесс, который не имеет ничего общего с родительским процессом. Таким образом, даже когда родитель умирает, ребенок продолжает. Я возвращаю PID ребенка, чтобы я мог отлаживать его позже, если захочу. Это то, что делает функция CreateProcess для Windows, и мне нужно реплицировать ее на Linux. – Dave

+1

В подходе с двойным форсированием новый процесс - это * не * дочерний элемент исходного процесса. Вы не можете есть торт и съесть его, если вы не взломаете что-то ужасно. – fuz

ответ

0

Вам не нужно, чтобы waitpid() на втором ребенке. Когда родитель процесса умирает, ребенок будет принят процессом init, поэтому не будет процесса зомби.

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

waitpid() получит статус выхода процесса. Неважно, когда процесс действительно вышел.

+0

Но с текущим кодом, как я понимаю, существует вероятность того, что возвращенный процесс может быть выполнен до (или во время) вызова exec. Я должен гарантировать, что waitpid возвращается только после завершения exec. – Dave

+2

Если вы хотите дождаться завершения 'execvp()' дочернего элемента, не делайте двойной 'fork()'. – jxh

0

(Немного уточнение: что ты называешь ребенка, на самом деле ваш внук Это ребенок процесса, который только что отделилась и умер..)

ли нужен второй waitpid к ждать, пока ребенок закончит exec?

Вы не можете. Это ваш внук, и вы можете только ждать своих прямых детей. Кроме того, поскольку родитель вашего внука умер, ваш внук теперь был репарирован для init (так это на самом деле ваш бывший внук).

Ожидает ли возвратный звонок при вызове exec?

Waitpid возвращается, когда данный PID умирает/выходы или сразу же, если это уже зомби. Исполнение вызывается у внука. Ваши ожидающие вызовы вовсе не связаны с процессами, которые не являются вашими прямыми дочерними элементами (если только вы не используете вспомогательную функцию, ограниченную Linux).

ли waitpid вернуться, даже если выход или Exec были вызваны, прежде чем waitpid?

Waitpid только когда возвращается, когда прислуживал PID (который должен быть ваш прямой ребенок) мертв. Если это еще не так, он будет блокироваться.

+0

Верно, что я не могу назвать waitpid у внука, но если вы посмотрите на код, мой второй waitpid будет сразу после второй вилки. То есть, ребенок будет ждать на внуке, но вы говорите, что exec не вызовет этого. Также о состоянии гонки. Что делать, если возвращенный процесс выполняется до вызова exec? – Dave

+0

Если вы по-прежнему заботитесь о своем внуке, поскольку вы хотите дождаться его и иметь надежную * ссылку на него, вы должны были сделать это своим ребенком, а не отказаться от него с помощью двойного форкирования. (* Если процесс с определенным pid является вашим ребенком, вы не можете использовать этот pid как надежную ссылку на него, потому что процессы приходят и уходят, и их pids возвращаются). – PSkocik

Смежные вопросы