2010-03-08 23 views
1

프로그램 내에서 다른 fork() 함수로 생성 된 하위 프로세스를 구분할 수있는 방법이 있습니까?fork() 내의 fork()

global variable i; 

SIGCHLD handler function() 
{ 
    i--; 
} 

handle() 
{ 
    fork() --> FORK2 
} 

main() 
{ 
    while(1) 
    { 
    if(i<5) 
    { 
     i++; 
     if((fpid=fork())==0) --> FORK1 
      handle() 
     else (fpid>0) 
      ..... 
    } 
    } 
} 

FORK1 및 FORK2에 의해 생성 된 하위 프로세스를 구별 할 수있는 방법이 있습니까? 왜냐하면 SIGCHLD 핸들러 함수에서 전역 변수 'i'의 값을 감소시키고 FORK1에 의해 생성 된 프로세스에 대해서만 감소시켜야하기 때문입니다.

배열을 사용하고 자식 프로세스 ID를 저장하려고했습니다. FORK1에서 작성한 프로세스이며 상위 프로세스에서 수행합니다. 죽은 아이의 프로세스 ID 배열 내에있는 경우 내가 '난'단지의 값을 감소시킵니다 ...

하지만 다음과 같은 시나리오

자식 1, 상위 1에 문제에 직면, 자식 1은 사망 제대로 업데이트되는 배열을 상위 1 후 살해되기 때문에는, 자식 2자식 2는

Incase의 자식 1의 parent2, 죽였다.

하지만 child2의 경우 pid 값이 parent2에 의해 배열에서 업데이트되기 전에 어떤 결과가 발생합니까? 자식 2 PID 값이 배열에 없으므로 SIGCHLD 신호 처리기 함수 내부에서 'i'값이 그에 따라 감소하지 않습니다.

그래서이 문제에 대한 더 나은 해결책이 있습니까 ??

+0

가능한 복제본 : http://stackoverflow.com/questions/340283/avoiding-a-fork-sigchld-race-condition – jschmier

+0

흠 ... 실제로 나는 그것을 이전에 발견하지 못했습니다 .. – codingfreak

+0

어떻게 신호 처리기를 설정하고 있습니까? ? 'signal','bsd_signal' 또는'sigaction'을 사용합니까? – Random832

답변

2

당신은 이미 당신이 SIGCHLD 핸들러에서 i의 가치를 감소하고자하는 PID를 목록을 저장하고 있기 때문에, 목록을 업데이트하는 동안 추가 SIGCHLD을 받고 당신을 트립 될 수있는 부분이다.

sigprocmask()을 사용하여 신호 처리기를 실행하는 동안 추가 SIGCHLD 신호를 마스크/차단할 수 있습니다. 다른 SIGCHLD 수신에 대한 걱정없이 프로세스 ID의 배열/목록을 업데이트 할 수있는 충분한 시간을 제공해야합니다. 블록 처리 된 마스크는 신호 처리 루틴이 끝나면 원래 값으로 되돌려 야합니다.

에 한번 당신의 SIGCHLD 처리기에 다음과 유사한 추가 :

이 질문을 다시 검토 한 후, 난 당신이 경주의 실행 조건을 가지고 볼

sigset_t mask; 
sigset_t orig_mask; 

sigemptyset (&mask); 
sigaddset (&mask, SIGCHLD); 

/* temporarily mask/block SIGCHLD signals and save original mask */ 
if (sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0) { 
    perror ("sigprocmask - %s", strerror(errno)); 
} 

/* process SIGCHLD via waitpid() and update PID list as necessary */ 
... 

/* restore original mask */ 
if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) { 
    perror ("sigprocmask - %s", strerror(errno)); 
} 

업데이트를하는 자식 프로세스에서 상위 프로세스가 PID를 목록에 추가하기 전에 종료됩니다.

가능한 해결 방법 중 하나는 여전히 임계 섹션 동안 SIGCHLD 신호를 차단하는 데 sigprocmask()을 사용하는 것입니다. 이 경우 fork()으로 전화하기 전에 SIGCHLD 신호를 차단하고 PID가 목록에 추가 된 후 상위 코드에서 블록을 해제해야합니다. 자식이 사망하면 신호를 차단 해제 한 후에 신호 처리기가 호출되며 이는 PID가 목록에 있음을 보장합니다.

+0

실제로 문제가 발생하지 않습니다. 배열 처리 SIGCHLD 신호 처리기 함수의 List ... 처음에는 자식 프로세스의 프로세스 ID로 배열을 업데이트하는 작업이 부모 프로세스에 의해 수행됩니다. 따라서 실행 순서가 .... child1, parent1, child2, child3, parent2, parent3 ...와 같은 시나리오에서 parent2 코드가 실행되기 전에 child2가 종료되면 ARRAY는 결과로 child2 PID로 업데이트되지 않습니다. SIGCHLD 신호 처리기는 pid가 배열에 없기 때문에 i 값을 감소시키지 않습니다. – codingfreak

+0

이제는 문제를 더 잘 이해할 수있게되었으므로 적절하게 응답을 업데이트했습니다. – jschmier

+0

fork() 전에 SIGCHLD 신호를 차단하고 부모 프로세스에서 블록을 해제해야한다는 것을 의미합니까 ?? – codingfreak

0

사용 : 나는 잘 이해한다면

getppid() function . 
+0

당신은 SIGCHILD 시그널 핸들러 함수에서 getppid()를 사용해야한다는 것을 의미합니까? 이 경우에는별로 유용하지 않습니다 ... ?? – codingfreak

0

, 당신은 waitpid() 시스템 호출에 관심이있을 수 있습니다. 특정 어린이를 기다릴 수 있습니다 (주어진 pid). 따라서 fork1과 fork2에 의해 생성 된 PID를 추적한다면 fork1의 자식이 죽은 경우에만 i 변수를 감소시킬 수 있어야합니다.

+0

Inorder fork1에 의해 생성 된 모든 하위 프로세스에 대한 목록을 유지하려면 부모 프로세스에서 배열을 사용하여 자식 프로세스 ID 및 SIGCHLD 처리기 함수에서 배열을 업데이트하려면 해당 PID가있는 경우에만 i의 값을 줄이려고합니다. 배열 내에서 .. 하지만 문제가 있습니다 .. 자식 프로세스가 너무 빨리 부모 프로세스의 코드가 실행되지 않으면 배열이 적절한 값으로 업데이트되지 않습니다. – codingfreak