SIGCHLD와 waitpid() 또는 wait() 사이의 관계는 무엇입니까?

SIGCHLD와 waitpid() 또는 wait() 사이의 관계는 무엇입니까?

내 말이 맞다면 프로세스는 함수를 호출하여 하위 프로세스가 종료되거나 중지될 때까지 기다립니다 waitpid().wait()

waitpid()SIGCHLD 신호와 or 함수 사이의 관계는 무엇입니까 wait()?

  • 프로세스가 waitpid()또는 wait()함수를 호출할 때 하위 프로세스가 종료/중지될 때까지(SIGCHLD 신호를 보내기 전과 동일) 프로세스가 자체적으로 정지된다는 것이 맞습니까?

    ( 신호가 전송될 때까지 현재 프로세스를 일시 중단합니다. 그래서 SIGCHLD가 전송될 때까지를 제외하고 비슷한 pause()지 궁금합니다 .)waitpid()

  • SIGCHLD가 호출에 의해 일시 중단된 프로세스로 전송될 때 waitpid()SIGCHLD 핸들러 실행과 일시 중단에서 재개 사이의 순서는 무엇입니까 waitpid()?
    (다음 컴퓨터 시스템 예에서: 프로그래머의 관점에서 SIGCHLD 핸들러 호출 waitpid().)

감사해요.

void handler(int sig)
{
  int olderrno = errno;

  while (waitpid(-1, NULL, 0) > 0) {
    Sio_puts("Handler reaped child\n");
  }
  if (errno != ECHILD)
    Sio_error("waitpid error");
  Sleep(1);
  errno = olderrno;
}

int main()
{
  int i, n;
  char buf[MAXBUF];

  if (signal(SIGCHLD, handler1) == SIG_ERR)
    unix_error("signal error");

  /* Parent creates children */
  for (i = 0; i < 3; i++) {
    if (Fork() == 0) {
      printf("Hello from child %d\n", (int)getpid());
      exit(0);
    }
  }

  /* Parent waits for terminal input and then processes it */
  if ((n = read(STDIN_FILENO, buf, sizeof(buf))) < 0)
    unix_error("read");

  printf("Parent processing input\n");
  while (1)
    ;

  exit(0);
}

답변1

wait()은 1970년대의 쓸모없는 UNIX 시스템 호출이고, waitpid()1980년대의 쓸모없는 UNIX 시스템 호출입니다.

waitid()1988년에는 고급 인터페이스가 도입되었습니다.

signal()또한 1970년대의 오래된 인터페이스이기도 합니다. 가장 가까운 인터페이스가 호출되어 sigaction()신호의 동작을 제어할 수 있습니다. 귀하의 경우 일반적인 통화는 다음과 같습니다.

    struct sigaction sa; 

    sa.sa_sigaction = handler; 
    sigemptyset(&sa.sa_mask); 
    sa.sa_flags = SA_RESTART|SA_SIGINFO; 

    sigaction(SIGCHLD, &sa, NULL); 

에 추가하면 SA_NOCLDWAIT전혀 sa.sa_flags호출할 필요가 없으며 wait*()시스템은 wait*()호출될 때까지 좀비 프로세스를 유지하지 않습니다.

추가되면 SA_NOCLDSTOPcild 프로세스가 종료될 때 SIGCHLD 핸들러가 호출되지 않습니다.

SIGCHLDa가 생성 되면 함수가 호출됩니다.

void handler(int sig, siginfo_t *sip, void *context)

자식 프로세스가 죽을 때. 이 매개변수는 sig신호 번호로 채워지고 , 두 번째 매개변수는 아래와 같이 SIGCHLD호출로 얻은 동일한 정보로 채워집니다 .waitid()

struct siginfo si;

ret = waitid(P_PID, pid, &si, WEXITED|WSTOPPED|WTRAPPED);

따라서 자식 프로세스의 상태에 관심이 없다면 시스템에 알릴 수 있고, 자식 프로세스를 호출하는 데는 관심이 없지만 wait*()여전히 프로세스 상태를 얻고 싶다면 시스템에 알리고 정보를 사용할 수 있습니다. 신호 처리기 함수의 두 번째 매개변수에 있습니다.

하위 프로세스가 종료되고 struct siginfo확인되면 다음 필드가 채워집니다.

si.si_signo   /* The signal number SIGCHLD */
si.si_code    /* The reason for the child to exit */
si.si_status  /* Either the parameter to exit(r) or signal number */
si.si_pid     /* The process id of the child that died */

si.si_code값이 포함 CLD_EXITED되면 완전한 si.si_status32비트 코드가 포함됩니다(POSIX 시스템의 경우) exit().

, 또는 가 포함 si.si_code된 경우 상태 변경을 발생시킨 신호 번호가 포함 됩니다 .CLD_KILLEDCLD_DUMPEDCLD_TRAPPEDCLD_STOPPEDCLD_CONTINUEDsi.si_status

답변2

설치된 경우 커널은 하위 프로세스의 상태가 변경될 때(일반적으로 종료) 프로세스에서 신호 처리기를 호출하지만 기본적으로 하위 프로세스를 가져오지 않습니다. 하위 프로세스를 수집하려면 핸들러 내부 또는 외부에서 wait(2) 또는 waitpid(2)를 호출해야 합니다. SIGCHLD 핸들러를 설치할 때 sigaction(2)에 대한 옵션으로 SA_NOCLDWAIT를 지정하면 신호 핸들러가 전달된 후 커널이 자동으로 하위 프로세스를 획득하며 이를 획득하기 위해 wait(2) 호출이 필요하지 않습니다.

SIGCHLD와 관련된 sigaction(2) 매뉴얼 페이지의 SA_NOCLDSTOP 및 SA_NOCLDWAIT 옵션에 대한 설명을 참조하십시오.

또한 SA_SIGINFO를 지정하여 세 개의 인수로 구성된 신호 처리기를 사용할 수 있도록 하는 signal(2) 대신 sigaction(2) 사용을 고려하십시오. siginfo_t 구조 참조에는 SIGCHLD가 전달되는 이유에 대한 추가 유용한 정보가 포함됩니다.

답변3

논평할 포인트가 충분하지 않지만 이것이 귀하의 질문에 대한 답변이 될 것입니다.

https://www.tutorialspoint.com/unix_system_calls/waitpid.htm#:~:text=%20waitpid()%20system%20call,options%20argument%2C%20as%20Description%20은 다음과 같습니다..

발생한 신호는 SIGCHLD 예에서 해당 특정 신호 유형에 대해 설정한 핸들러 기능을 트리거합니다.

여기에 예가 있습니다. https://stackoverflow.com/questions/13792900/signal-and-sigchld-what-does-it-do

위 링크에서 볼 수 있듯이 wait()가 핸들러 내부에 있을 필요는 없습니다.

자식 프로세스가 종료될 때까지 기다립니다.

따라서 기본적으로 직접적인 관계는 없습니다. 단지 분기된 하위 프로세스가 종료되면 SIGCHLD 신호가 생성되고 wait()는 하위 프로세스가 적절하게 종료될 때까지 기다립니다.

관련 정보