2017-11-03 13 views
1

나는 리눅스에서 C로 된 쉘 코드를 작성한다. 여기서는 여러 개의 파이프를 구현해야한다. (예를 들어 A | B | c | D 여기서 A, B, C, D는 명령입니다). 쉘은 각 명령에 대해 동일한 pgid로 개별 프로세스를 생성하고 pipe() 시스템 콜을 사용하여 입력 및 출력을 연결합니다. 모든 자식이 만들어지면 부모는이 pgid를 tcsetpgrp()를 사용하여 포 그라운드로 와서 배경으로 이동합니다. 모든 것이 작동하지만 A, B, C, D를 실행하는 자식이 끝나면 자식 1을 처리하는 child1만이 죽고 sigchild 처리기와 다른 자식에 의해 처리됩니다. Ctrl + c를 누를 때까지 아무것도하지 않습니다. ctrl + c를 누르면 다른 모든 자식이 신호 처리기에서 수확되고 sigsuspend에있는 부모가 깨어나 다시 포 그라운드로 돌아옵니다.많은 아이들 중 한 명의 자식 만 죽고 나머지는 Ctrl + C를 기다린다

아무도 왜 어린이 1 만 죽고 다른 어린이는 끝내지 않는 컨트롤인지 이해할 수 있습니까?

다음은 SIGINT 핸들러 코드입니다. 그것이 아이의 필요한 수를 생성 한 후

공극 sigchld_handler (INT의 S) {

int olderrno = errno; 
sigset_t mask_all; 
sigset_t prev_all; 

sigfillset(&mask_all); 
while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { 
    sigprocmask(SIG_BLOCK, &mask_all, &prev_all); 
    NoOfChildrenToBeReaped--; 
    sigprocmask(SIG_SETMASK, &prev_all, NULL); 
} 
errno = olderrno; 

} 여기

는 부모 코드이다. 여기

//Get the pid of the first child and set it as the pgid of all the sibling children. 
if (i == 0) { 
    pgid = pid; 
} 
setpgid(pid, pgid); 

그리고

는, 부모가 백그라운드로 이동하는 과정입니다 아직 수확 할 얼마나 많은 아이들의 트랙을 유지하고,() sigsuspend 후 다시 전경에 온다.

if (BGProc) { 
    if (tcsetpgrp(STDIN_FILENO, pgid) == -1) { 
     printf(EXEC_ERROR, "Error in tcsetpgrp"); 
    } 

    while (NoOfChildrenToBeReaped) { 
     sigsuspend(&masknone); 
    } 

    signal(SIGTTOU, SIG_IGN); 
    if (tcsetpgrp(STDIN_FILENO, getpid()) == -1) { 
     printf(EXEC_ERROR, "Error in tcsetpgrp"); 
    } 
} 

모든 도움을 주시면 감사하겠습니다.

감사합니다.

+1

왜 어린이 A는 사망하나요? 프로세스가 완료 되었기 때문에? 그런 다음 stdin에서 읽는 다음 자식 B는 EOF를 가져와 종료해야합니다. 이제는 이것이 일어나지 않기 때문에, A가 쓰고 B가 읽는 파이프의 쓰기 끝이 닫히지 않을 가능성이 있습니다. 자녀를 분기 한 후에 주 프로세스 (그리고 해당되는 경우 다른 모든 프로세스)에서 글 쓰기 끝을 제대로 닫습니까? 불행히도 코드의 일부는 표시하지 않습니다. – Ctx

+0

예, 하위 A는 작업을 마치고 정상적으로 종료됩니다. 파이프가 올바르게 닫혔는지 확신합니다. 코드의 해당 부분을 추가하고 싶지만 매우 큰 부분이며 과제의 일부입니다. 나는 그것의 얼마를 여기에서 배치 할 수 있는지 잘 모르겠습니다. – Shubs

+0

시스템 환경에서 프로세스 a가 종료 된 후 프로세스 b (strace 포함)를 추적하십시오. 그것은 어디서 멈 춥니 까? – Ctx

답변

0

파이프에 사용 된 FileDescriptors가 올바르게 닫히지 않았기 때문에 실제로 이것은 바보 같은 실수 였고 실제로 문제가되었습니다. @ 지적 해 주시고 의견을 통해 좋은 제안을 해주셔서 감사합니다.

for (i = 0; i < 2 * NoOfPipes; i++) 
    close(pipefds[j]); //should have been "i". 

"for"코드를 간과하고 당연시했습니다.