2014-10-16 8 views
1

Я пытаюсь создать несколько процессов от одного и того же родителя, но он всегда заканчивается большим количеством процессов, чем ожидалось. Я не мог понять, как это сделать и вам нужна помощь.Как разбить несколько процессов от одного и того же родителя?

я нашел кусок кода в Интернете и попробовал,

int main() 
{ 
    pid_t pid=0; 
    int i=0; 
    for (i=0; i<3; i++) 
    { 
     pid=fork(); 
     switch(pid) 
     { 
      case 0: 
      { 
       cout<<"\nI am a child and my pid is:"<<getpid(); 
       cout<<endl; 
       exit(0); 
       break; 
      } 
      default: 
      { 
       cout<<"\nI am a parent and my pid is: "<<getpid(); 
       cout<<"\nMy child pid is: "<<pid; 
       cout<<endl; 
       wait(NULL); 
       break; 
      } 
     } 
    } 
    return 0; 
} 

Этот код работает и создает 3-х детей из того же родителя. Однако, похоже, это потому, что после того, как был создан каждый дочерний процесс, он был немедленно прекращен. Поэтому в следующем раунде цикла for не будет развиваться процесс внука. Но мне нужно, чтобы эти дочерние процессы работали на некоторое время, и им нужно общаться с родителями.

+0

Производит ли он выход «Я ребенок ...»? Как только вы вызываете exit, процесс завершается. Причина, по которой они заканчиваются так быстро, заключается в том, что вы ничего не делаете в этом процессе. Вы должны вызывать некоторую интенсивную работу с ЦП, а не печатать и немедленно выходить. – Micah

+0

Это не проблема с fork, а простая логическая проблема. 'fork()' возвращает 0 в дочернем элементе. Отметьте на бумаге, что здесь происходит, без «выхода» для ребенка, цикл снова запускается, а «fork» выполняется снова. То, что вы хотите сделать, это * if * процесс - это ребенок, вы выходите из цикла, * else * вы продолжаете цикл и forking ... – Leiaz

+0

Спасибо вам за то, что ответили на мой вопрос. Я изменил свой код, используя if..else вместо case..switch и добавив разрыв в конце раздвоенного дочернего процесса, чтобы выйти из цикла, и он работает !!!!! Я получил именно то, что хочу! – Karen

ответ

1

Дочерний процесс может немедленно разорвать петлю, чтобы продолжить свою работу за пределами

int main() 
{ 
    cout<<"\nI am a parent and my pid is: "<<getpid()<<endl; 

    pid_t pid; 
    int i; 
    for (i=0; i<3; i++) 
    { 
     pid=fork(); 
     if(pid == -1) 
     { 
      cout<<"Error in fork()"<<endl; 
      return 1; 
     } 
     if(pid == 0) 
      break; 
     cout<<"My child "<<i<<" pid is: "<<pid<<endl; 
    } 

    if(pid == 0) 
    { 
     cout<<"I am a child "<<i<<" and my pid is "<<getpid()<<endl; 
     wait(NULL); // EDIT: this line is wrong! 
    } 
    else 
    { 
     cout<<"I am a parent :)"<<endl; 
     wait(NULL); // EDIT: this line is wrong! 
    } 
    return 0; 
} 

EDIT
В wait(NULL) линии неверны. Если в процессе нет активных детей, wait() не имеет никакого эффекта, поэтому здесь бесполезно для детей. OTOH в родительском процессе wait() приостанавливает выполнение до любых детей. У нас здесь трое детей, так что нужно было бы wait() три раза. Кроме того, нельзя заранее знать порядок завершения работы с детьми, поэтому для этого нам понадобится гораздо более сложный код. Что-то вроде этого:

struct WORK_DESCRIPTION { 
    int childpid; 
    // any other data - what a child has to do 
} work[3]; 

for(i=1; i<3; i++) { 
    pid=fork(); 
    ... 
    work[i].childpid = pid; 
} 

if(pid == 0) // in a child 
{ 
    do_something(work[i]); 
} 
else 
{ 
    int childpid; 
    while(childpid = wait(NULL), childpid != 0) 
    { 
     // a child terminated - find out which one it was 

     for(i=0; i<3; i++) 
      if(work[i].childpid == childpid) 
      { 
       // use the i-th child results here 
      } 
    } 
    // wait returned 0 - no more children to wait for 
} 
+0

Я все еще немного смущен о pid здесь. В вышеприведенном коде вы сначала разворачиваете всех трех детей в цикле for, затем используете if (pid == 0), чтобы каждый из них печатал сообщение. Это нормально, потому что все они делают то же самое. Но что, если я хочу, чтобы каждый ребенок выполнял другую работу, как я мог выбрать ребенка в этом случае? То, что я сделал, - это развить ребенка, если pid == 0, сделать что-то; else (back to parent), fork 2nd child, если pid == 0, выполните другую вещь и так далее. Есть ли другой способ сделать это? – Karen

+0

Каждый дочерний процесс наследует копию своих родительских данных и переменную 'i' среди них (вот почему я печатаю ее здесь). Поэтому вы можете сделать 'switch (i) {...}', чтобы выбрать подходящую работу для каждого ребенка. Предупреждение: нет «назад к родительскому», я имею в виду, что дочерние процессы не возвращают ». Поскольку 'fork()' родитель и ребенок запускаются одновременно. Вам нужно 'wait()' в родительском процессе, если вы хотите синхронизировать его с дочерними элементами (например, использовать их результаты). – CiaPan

+0

@ Karen Отредактировал свой ответ. – CiaPan

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