Несколько fork () в переключателе приводят к экспоненциальному исполнению - PullRequest
1 голос
/ 09 августа 2011

У меня есть программа, которая выполняет несколько программ в зависимости от меня. Смотрите следующий блок кода:

for(i=0;i<5;i++){
 switch(i){
  case 0:
    if(fork())result=execl(transportProtoSnd,transportProtoSnd,RTPport, NULL);
    if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
    break;
 case 1:
    if(fork())result=execl(fecSnd,fecSnd,RTPport-1, nameOfTransportProto, NULL);
    if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
    break;
 case 2:
    if(fork())result=execl(fecRcv,fecRcv,RTPport-2, nameOfTransportProto, NULL);
    if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
    break;
 case 3:
    if(fork())result=execl(transportProtoRcv,transportProtoRcv, RTPport-3, NULL);
    if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
    break;
 }
}

Проблема в том, что дерево процессов выглядит так:

0:00  \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly Tests/NfqVerdictOnly 
0:00  |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 

Используя vfork (), я получаю лучшее поведение:

0:00  \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly Tests/NfqVerdictOnly 
0:00  |   \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |       \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |           \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 
0:00  |               \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly 

Но на самом деле это должно выглядеть так:

0:00 udevd --daemon
0:00  \_ udevd --daemon
0:00  \_ udevd --daemon

IIRC vfork () не использует состояние родительского процесса. Таким образом, я предотвращаю экспоненциальное разветвление в дереве ps 1. Однако при использовании vfork каждый дочерний элемент развивается из родительского дочернего элемента, см. Дерево 2. По моему мнению, с помощью fork () или vfork () дерево должно выглядеть как дерево ps 3.

С уважением

Ответы [ 3 ]

3 голосов
/ 09 августа 2011

На самом деле, вот что происходит.

if(fork())result=execl(transportProtoSnd,transportProtoSnd,RTPport, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}

Родительская вилка и немедленно исполняют (и, конечно, никогда не возвращаются).Это то, что делает if.Затем дочерний элемент проверяет фиктивное значение результата и продолжает порождать другую программу (i ++).

Таким образом, основная проблема заключается в том, что вы выполняете родительский процесс вместо дочернего.(что довольно странно).Вы должны делать что-то вроде:

if(fork() == 0) {
    execl(transportProtoSnd,transportProtoSnd,RTPport, NULL);
    /* If it reaches this handle error. */
}

Очевидно, вы должны проверять код возврата fork(2).

1 голос
/ 09 августа 2011

Со страницы man 'fork':

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

Что означает для вашей программы, что родительский процесс исполняется, а дочерний процесс продолжает цикл для разветвления других ... таким образом, дерево, ИМХО.Попробуйте инвертировать условие if.

0 голосов
/ 09 августа 2011

В дополнение к другим ответам, вы должны знать, что вы создаете зомби таким образом - по крайней мере, если у вас есть длительная «родительская» программа. Вы должны записать PID fork() ed процессов, возможно, в массиве, и сделать wait(), waitid() или waitpid().

...