source

부모 퇴출 후 자녀 프로세스를 정지시키는 방법

goodcode 2022. 8. 25. 23:49
반응형

부모 퇴출 후 자녀 프로세스를 정지시키는 방법

정확히 하나의 하위 프로세스를 생성하는 프로세스가 있다고 가정합니다.어떤 이유로든 부모 프로세스가 종료되면(통상 또는 비정상적으로 kill, ^C, assert failure 등) 자녀 프로세스를 정지합니다.어떻게 하면 좋을까요?


stackoverflow에 관한 유사한 질문:


Windows 의 stackoverflow 에 대해서도, 다음과 같은 질문이 있습니다.

에게 전해 할 수 .SIGHUP또는 신호) ""를 때 ("다른 신호")PR_SET_PDEATHSIGprctl() syscall을 . syscall about adda

prctl(PR_SET_PDEATHSIG, SIGHUP);

것은, 을 참조하십시오.man 2 prctl세한것 、 을을해해요요 。

편집: 이것은 Linux 전용입니다.

Linux 에서는 다음과 같은 부모 사망 신호를 자녀에 설치할 수 있습니다.

#include <sys/prctl.h> // prctl(), PR_SET_PDEATHSIG
#include <signal.h> // signals
#include <unistd.h> // fork()
#include <stdio.h>  // perror()

// ...

pid_t ppid_before_fork = getpid();
pid_t pid = fork();
if (pid == -1) { perror(0); exit(1); }
if (pid) {
    ; // continue parent execution
} else {
    int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
    if (r == -1) { perror(0); exit(1); }
    // test in case the original parent exited just
    // before the prctl() call
    if (getppid() != ppid_before_fork)
        exit(1);
    // continue child execution ...

포크 앞에 부모 프로세스 ID를 저장하고 그 후에 자식 프로세스 ID를 테스트하면 자아를 호출한 프로세스와 종료 사이의 레이스 조건이 제거됩니다.

또한 새로 생성된 자식에서는 자녀의 부모 사망 신호가 지워집니다.은 영향을 .execve().

모든 고아 입양을 담당하는 시스템 프로세스가 PID 1을 가지고 있는 것이 확실하다면 이 테스트는 단순화할 수 있습니다.

pid_t pid = fork();
if (pid == -1) { perror(0); exit(1); }
if (pid) {
    ; // continue parent execution
} else {
    int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
    if (r == -1) { perror(0); exit(1); }
    // test in case the original parent exited just
    // before the prctl() call
    if (getppid() == 1)
        exit(1);
    // continue child execution ...

그 가 「」라고 하는 것에 .initPID 1은 휴대할 수 없습니다.POSIX.1-2008은 다음을 지정합니다.

호출 프로세스의 모든 기존 하위 프로세스 및 좀비 프로세스의 부모 프로세스 ID는 구현 정의 시스템 프로세스의 프로세스 ID로 설정해야 합니다.즉, 이러한 프로세스는 특별한 시스템 프로세스에 의해 상속되어야 한다.

전통적으로 모든 고아들을 채택하는 시스템 프로세스는 PID 1, 즉 모든 프로세스의 조상인 init입니다.

Linux 또는 FreeBSD같은 최신 시스템에서는 다른 프로세스가 이 역할을 할 수 있습니다.예를 들어 Linux에서는 프로세스가 하위 프로세스의 모든 고아(Fedora 25의 예 참조)를 상속하는 시스템 프로세스로 자신을 확립하기 위해 호출할 수 있습니다.

같은 문제를 해결하려고 하는데 프로그램이 OS X에서 실행되어야 하기 때문에 Linux 전용 솔루션이 작동하지 않았습니다.

이 페이지의 다른 사람과 같은 결론에 도달했습니다.부모가 사망했을 때 자녀에게 통지하는 POSIX 호환 방법은 없습니다.그래서 저는 차선책인 아동 여론조사를 했습니다.

부모 프로세스가 사망하면(어떤 이유로든), 자녀의 부모 프로세스는 프로세스 1이 됩니다.아이가 단순히 정기적으로 폴링하는 경우 부모가 1인지 여부를 확인할 수 있습니다.만약 그렇다면, 아이는 퇴장해야 합니다.

이것은 좋은 것은 아니지만 동작합니다.또, 이 페이지의 다른 장소에서 제안하는 TCP 소켓/락 파일 폴링 솔루션보다 간단합니다.

하위 프로세스를 수정할 수 없는 경우 다음과 같은 작업을 수행할 수 있습니다.

int pipes[2];
pipe(pipes)
if (fork() == 0) {
    close(pipes[1]); /* Close the writer end in the child*/
    dup2(pipes[0], STDIN_FILENO); /* Use reader end as stdin (fixed per  maxschlepzig */
    exec("sh -c 'set -o monitor; child_process & read dummy; kill %1'")
}

close(pipes[0]); /* Close the reader end in the parent */

그러면 작업 제어가 활성화된 셸 프로세스 내에서 하위 프로세스가 실행됩니다.하위 프로세스가 백그라운드에서 생성됩니다.셸은 줄바꿈(또는 EOF)을 기다렸다가 아이를 죽입니다.

부모가 죽으면 이유야 어떻든 파이프의 끝을 닫게 될 거야하위 셸은 읽기로부터 EOF를 가져와 백그라운드 하위 프로세스를 종료합니다.

표준 POSIX 콜만을 사용하는 것은 불가능하다고 생각합니다.실제 삶처럼, 아이는 한번 태어나면 자신만의 삶이 있다.

부모 프로세스가 대부분의 가능한 종료 이벤트를 포착하고 그 시점에서 자녀 프로세스를 종료하려고 할 수 있지만, 항상 포착할 수 없는 이벤트가 있습니다.

를 들어,도 를를, 떤떤 、 a for a a a a a a를 잡을 수 .SIGKILL커널이 이 신호를 처리하면 해당 프로세스에 대한 알림 없이 지정된 프로세스가 종료됩니다.

유추하자면 - 유일한 표준적인 방법은 아이가 더 이상 부모가 없다는 것을 알게 되었을 때 자살을 하는 것이다.

Linux에서만 할 수 있는 .prctl(2) - 다른 답을 봐주세요. - 다른 답을 봐주세요.

몇몇 포스터는 이미 파이프와kqueue실제로 접속되어 있는 Unix 도메인소켓의 페어를 작성할 수도 있습니다.socketpair()은 ". " 입니다.SOCK_STREAM.

2가 합니다.fd1, fd2로 하다, 이제fork()fds를 하는 자.fd2로 fd1로 하다으로, 각 는 「」할 수 있게 되었습니다.poll()는 fd fd fd fd fd fd fd fd fd fd fd-fd fd-fd fd-fd fd-fd fd-fd fd-fdPOLLIN으로 하지 . 양쪽이 명확하게 하지 않는 한close()인 라이프 타임 에 fd는 합니다.POLLHUP플래그는 상대방의 종료를 나타내야 합니다(깨끗하든 말든 상관없습니다.이 이벤트가 통지되면 아이는 무엇을 할지(예: 죽을지) 결정할 수 있습니다.

#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>
#include <stdio.h>

int main(int argc, char ** argv)
{
    int sv[2];        /* sv[0] for parent, sv[1] for child */
    socketpair(AF_UNIX, SOCK_STREAM, 0, sv);

    pid_t pid = fork();

    if ( pid > 0 ) {  /* parent */
        close(sv[1]);
        fprintf(stderr, "parent: pid = %d\n", getpid());
        sleep(100);
        exit(0);

    } else {          /* child */
        close(sv[0]);
        fprintf(stderr, "child: pid = %d\n", getpid());

        struct pollfd mon;
        mon.fd = sv[1];
        mon.events = POLLIN;

        poll(&mon, 1, -1);
        if ( mon.revents & POLLHUP )
            fprintf(stderr, "child: parent hung up\n");
        exit(0);
    }
}

의 개념 코드를할 수 ../a.out &다양한 신호에 의해 부모 PID를 정지시키는 실험을 할 수 있는 시간은 약 100초입니다.그렇지 않으면 단순히 종료됩니다.자녀:부모의 전화를 끊다

용용 using using using using using using method 를 사용한 방법SIGPIPE 이 에서는, 「」, 「」, 「RADIUS TEMPLE」을 시험할.write()discl.discl.discl을 클릭합니다.

방법은 대칭적이기도 합니다. 즉, 프로세스가 서로의 존재를 감시하기 위해 동일한 채널을 사용할 수 있습니다.

이 솔루션은 POSIX 함수만 호출합니다.Linux와 FreeBSD에서 시도했습니다.다른 Unix에서도 동작할 수 있다고 생각합니다만, 실제로 테스트해 본 적은 없습니다.

다음 항목도 참조하십시오.

  • unix(7) 페이지 중 man 페이지unix(4) FreeB의 SD 우경 、poll(2),socketpair(2),socket(7)Linux 서 linux 。

이 솔루션은 나에게 효과가 있었다.

  • stdin 파이프를 아이에게 전달합니다. 스트림에 데이터를 쓸 필요가 없습니다.
  • 자식은 stdin에서 EOF까지 무한히 읽습니다.EOF는 부모가 사라졌음을 나타냅니다.
  • 이것은 부모가 떠난 것을 감지하기 위한 완벽한 휴대용 방법입니다.부모가 크래시해도 OS는 파이프를 닫습니다.

이는 부모가 살아있을 때만 의미가 있는 워커형 프로세스를 위한 것입니다.

Linux 고유의 또 다른 방법은 부모를 새 PID 네임스페이스에 생성하는 것입니다.이 1이 , 이 PID 1로 .SIGKILL.

새로운 네임스페이스를 하려면 "PID"가 필요합니다.CAP_SYS_ADMIN이 방법은 효과적이며 에 대한 이후 하지 않습니다.

clone(2), pid_namespaces(7) 및 unshare(2)참조하십시오.

완전성을 위해서.macOS에서는 kqueue를 사용할 수 있습니다.

void noteProcDeath(
    CFFileDescriptorRef fdref, 
    CFOptionFlags callBackTypes, 
    void* info) 
{
    // LOG_DEBUG(@"noteProcDeath... ");

    struct kevent kev;
    int fd = CFFileDescriptorGetNativeDescriptor(fdref);
    kevent(fd, NULL, 0, &kev, 1, NULL);
    // take action on death of process here
    unsigned int dead_pid = (unsigned int)kev.ident;

    CFFileDescriptorInvalidate(fdref);
    CFRelease(fdref); // the CFFileDescriptorRef is no longer of any use in this example

    int our_pid = getpid();
    // when our parent dies we die as well.. 
    LOG_INFO(@"exit! parent process (pid %u) died. no need for us (pid %i) to stick around", dead_pid, our_pid);
    exit(EXIT_SUCCESS);
}


void suicide_if_we_become_a_zombie(int parent_pid) {
    // int parent_pid = getppid();
    // int our_pid = getpid();
    // LOG_ERROR(@"suicide_if_we_become_a_zombie(). parent process (pid %u) that we monitor. our pid %i", parent_pid, our_pid);

    int fd = kqueue();
    struct kevent kev;
    EV_SET(&kev, parent_pid, EVFILT_PROC, EV_ADD|EV_ENABLE, NOTE_EXIT, 0, NULL);
    kevent(fd, &kev, 1, NULL, 0, NULL);
    CFFileDescriptorRef fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd, true, noteProcDeath, NULL);
    CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack);
    CFRunLoopSourceRef source = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0);
    CFRunLoopAddSource(CFRunLoopGetMain(), source, kCFRunLoopDefaultMode);
    CFRelease(source);
}

SIGINT를 잡기 위해 트랩 핸들러를 설치합니다. SIGKILL을 잡지 못하는 다른 포스터는 맞지만 아직 살아 있으면 자녀 과정이 끊어집니다.

.lock 파일을 배타적 액세스로 열고, 그 파일을 열려고 하는 자녀에게 폴링을 실시합니다.열기에 성공하면 자녀 프로세스가 종료됩니다.

또 다른 답변에 영감을 받아 다음과 같은 All-POSIX 솔루션을 생각해냈습니다.일반적인 생각은 부모와 자녀 사이에 하나의 목적을 가진 중간 프로세스를 작성하는 것입니다.부모가 사망했을 때 주의하고 아이를 명시적으로 죽인다.

이 유형의 솔루션은 하위의 코드를 수정할 수 없는 경우에 유용합니다.

int p[2];
pipe(p);
pid_t child = fork();
if (child == 0) {
    close(p[1]); // close write end of pipe
    setpgid(0, 0); // prevent ^C in parent from stopping this process
    child = fork();
    if (child == 0) {
        close(p[0]); // close read end of pipe (don't need it here)
        exec(...child process here...);
        exit(1);
    }
    read(p[0], 1); // returns when parent exits for any reason
    kill(child, 9);
    exit(1);
}

이 방법에는 다음 두 가지 작은 경고가 있습니다.

  • 만약 당신이 의도적으로 중간 과정을 죽인다면, 부모가 죽었을 때 아이는 죽지 않을 것입니다.
  • 자녀가 부모보다 먼저 종료하면 중간 프로세스가 원래 자식 pid를 종료하려고 합니다.이러한 프로세스는 다른 프로세스를 참조할 수 있습니다.(이 문제는 중간 프로세스에서 더 많은 코드를 사용하여 수정할 수 있습니다.)

참고로, 제가 사용하고 있는 실제 코드는 Python입니다.다음은 완전성을 위한 설명입니다.

def run(*args):
    (r, w) = os.pipe()
    child = os.fork()
    if child == 0:
        os.close(w)
        os.setpgid(0, 0)
        child = os.fork()
        if child == 0:
            os.close(r)
            os.execl(args[0], *args)
            os._exit(1)
        os.read(r, 1)
        os.kill(child, 9)
        os._exit(1)
    os.close(r)

환경을 사용하는 부모 pid를 자녀에게 전달하고 자녀로부터 /proc/$ppid가 존재하는지 정기적으로 확인합니다.

다른 사람들이 지적한 바와 같이 부모가 퇴장할 때 부모 pid가 1이 되는 것에 의존하는 것은 포터블하지 않습니다.특정 부모 프로세스 ID를 기다리는 대신 ID가 변경될 때까지 기다립니다.

pit_t pid = getpid();
switch (fork())
{
    case -1:
    {
        abort(); /* or whatever... */
    }
    default:
    {
        /* parent */
        exit(0);
    }
    case 0:
    {
        /* child */
        /* ... */
    }
}

/* Wait for parent to exit */
while (getppid() != pid)
    ;

최대 속도로 폴링하지 않으려면 필요에 따라 마이크로 슬립을 추가합니다.

이 옵션은 파이프를 사용하거나 신호에 의존하는 것보다 간단해 보입니다.

자식 프로세스와 부모 프로세스 간의 파이프가 있습니까?이 경우 쓰기를 하면 SIGPIPE가 수신되거나 읽을 때 EOF가 수신됩니다.이러한 상태가 검출될 수 있습니다.

「의 「 「부모의 「의 「」코드.fork()SIGCHLD라고 합니다.

당신의 경우는 불가능할 수도 있지만, 효과가 있을 때는 귀엽습니다.

POSIX에서exit(),_exit() ★★★★★★★★★★★★★★★★★」_Exit()함수는 다음과 같이 정의됩니다.

  • 이 프로세스가 제어 프로세스인 경우에는 호출 프로세스에 속하는 제어 단말기의 전경 프로세스군 내의 각 프로세스에 SAHUP 신호를 송신해야 한다.

따라서 부모 프로세스를 프로세스 그룹의 제어 프로세스로 설정할 경우 부모가 종료할 때 자녀에게 SAHUP 신호가 전송됩니다.부모가 충돌했을 때 그런 일이 일어나는지 확실하진 않지만, 그렇게 되는 것 같아요.확실히 충돌하지 않는 케이스라면 잘 될 겁니다.

「 Definitions이나 「 Services for 」(「Definitions」)의 「System Services information for」(「 서비스 정보」)를 포함해, 을 읽어 둘 가 있는 경우가 .exit() ★★★★★★★★★★★★★★★★★」setsid() ★★★★★★★★★★★★★★★★★」setpgrp()를 알 수. - 도 알 수 .

7년이 지났지만 개발 중에 webpack-dev-server를 시작해야 하고 백엔드 프로세스가 정지되면 종료해야 하는 SpringBoot 어플리케이션을 실행 중이기 때문에 이 문제가 발생하게 되었습니다.

사용하려고 합니다.Runtime.getRuntime().addShutdownHookWindows 10 에 windows windows windows windows 、 Windows 7 windows windows windows windows windows windows 。

하는 전용 를 사용하거나 가 종료될 때까지 대기하는 스레드를 InterruptedExceptionwindows Windows 버버모모서작작 。

private void startWebpackDevServer() {
    String cmd = isWindows() ? "cmd /c gradlew webPackStart" : "gradlew webPackStart";
    logger.info("webpack dev-server " + cmd);

    Thread thread = new Thread(() -> {

        ProcessBuilder pb = new ProcessBuilder(cmd.split(" "));
        pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        pb.directory(new File("."));

        Process process = null;
        try {
            // Start the node process
            process = pb.start();

            // Wait for the node process to quit (blocking)
            process.waitFor();

            // Ensure the node process is killed
            process.destroyForcibly();
            System.setProperty(WEBPACK_SERVER_PROPERTY, "true");
        } catch (InterruptedException | IOException e) {
            // Ensure the node process is killed.
            // InterruptedException is thrown when the main process exit.
            logger.info("killing webpack dev-server", e);
            if (process != null) {
                process.destroyForcibly();
            }
        }

    });

    thread.start();
}

부모가 사망하면 고아 PPID는 1로 변경되며, 본인 PPID만 확인하면 됩니다.어떤 면에서는, 이것은 위에서 말한 폴링입니다.이를 위한 셸 조각은 다음과 같습니다.

check_parent () {
      parent=`ps -f|awk '$2=='$PID'{print $3 }'`
      echo "parent:$parent"
      let parent=$parent+0
      if [[ $parent -eq 1 ]]; then
        echo "parent is dead, exiting"
        exit;
      fi
}


PID=$$
cnt=0
while [[ 1 = 1 ]]; do
  check_parent
  ... something
done

나는 부모와 자식 사이에 파이프를 만드는 것이 빠르고 더러운 방법이라고 생각한다.부모가 퇴장하면 자녀는 SIGPIPE를 받게 됩니다.

pid 0 에 신호를 송신하는 경우는, 예를 들면,

kill(0, 2); /* SIGINT */

이 신호는 전체 프로세스 그룹에 전송되므로 사실상 아이를 죽일 수 있습니다.

다음과 같은 방법으로 쉽게 테스트할 수 있습니다.

(cat && kill 0) | python

다음 누르면 ^D라는 ."Terminated"Python 인터프리터는 stdin이 닫혔기 때문에 그냥 나가는 것이 아니라 실제로 죽임을 당했음을 나타냅니다.

C++에서 분기된 하위 프로세스로 JVM 인스턴스를 생성할 때 상위 프로세스가 완료된 후 JVM 인스턴스를 올바르게 종료할 수 있는 유일한 방법은 다음과 같습니다.만약 이것이 최선의 방법이 아니었다면 누군가가 댓글로 피드백을 줄 수 있기를 바랍니다.

) 콜 1)prctl(PR_SET_PDEATHSIG, SIGHUP)된 자녀 에 대해 설명합니다.execv , , , , 입니다.

2)이 될 을 Java 한 후 2) 부모 셧다운 훅을 합니다.PID1와 같습니다 자바 응용 프로그램, 열심히 했잖아요 폐쇄 고리를 넣으세요.Runtime.getRuntime().halt(0)은 를 ps사령부(: 어떻게 내가 Java또는 JRuby에 리눅스에 PID를 찾나요?).

EDIT 130118:

그것은 이건 하면 안 되는 강력한 해결책 보인다.나는 아직도 약간 무슨 일이 일어나고 있는지 미묘한 차이를 이해하는 것이었지만screen/SSH 세션에서 이 응용 프로그램을 실행 나는 여전히 가끔씩은 고아 자바 가상 머신 지원 과정을 얻고 있었습니다 힘들어 하는 거야

대신에 PPID의 자바 앱 투표의, 나는 간단히 그 정지 훅 연기하는 정리 위로서 어려운 중단 했어요. 꼭 발음을 했어요.waitpid그 원동력이 되는 한편 자식 프로세스에 C++부모 앱에서는 시간이었다 모든 것을 종료하기 위해.아이가 과정은 부모들은 아이들을 해지하는 것을 확인하기 위해 기존 참고 문헌을 활용한다는 것은 그것이 종료됨을 보장한다 이것은 더 건전한 해결책인 것처럼 보인다.그것을 기쁘시게 해는 부모 프로세스 종료되고 아이들은 만약 그들이 탈퇴에 앞서 고아가 되고 있었는지를 알아내려 시도해야 할 것이 이전 솔루션에 비교해 보라.

2솔루션 완벽한 수 없다고 판결했다.

signalkill(-pid)을 하면 모든 를 kill.1SIGTERM을 죽인다.
분명 이 방법이지만, 대부분의 경우에 와서 필요 모든 자식 프로세스 기억하지 않도록 매우 단순한 일하나"-9을 죽이"를 다룰 수가 없다.


    var childProc = require('child_process').spawn('tail', ['-f', '/dev/null'], {stdio:'ignore'});

    var counter=0;
    setInterval(function(){
      console.log('c  '+(++counter));
    },1000);

    if (process.platform.slice(0,3) != 'win') {
      function killMeAndChildren() {
        /*
        * On Linux/Unix(Include Mac OS X), kill (-pid) will kill process group, usually
        * the process itself and children.
        * On Windows, an JOB object has been applied to current process and children,
        * so all children will be terminated if current process dies by anyway.
        */
        console.log('kill process group');
        process.kill(-process.pid, 'SIGKILL');
      }

      /*
      * When you use "kill pid_of_this_process", this callback will be called
      */
      process.on('SIGTERM', function(err){
        console.log('SIGTERM');
        killMeAndChildren();
      });
    }

마찬가지로 프로세스를 호출하면 위와 같이 '종료' 핸들러를 설치할 수 있습니다.어디론가 나가다주의: Ctrl+C 및 갑작스러운 크래시는 OS에 의해 자동으로 처리되어 프로세스 그룹이 종료됩니다.따라서 여기서는 종료됩니다.

2. chjj/pty.js를 사용하여 제어 단말기가 연결된 상태에서 프로세스를 생성합니다.
어쨌든 현재 프로세스를 종료하면 (OS에 의해) 모든 하위 프로세스도 자동으로 종료됩니다.현재 프로세스가 터미널의 다른 쪽을 차지하고 있기 때문에 현재 프로세스가 정지하면 자 프로세스가 SIGPIPE를 취득하여 정지한다고 생각합니다.


    var pty = require('pty.js');

    //var term =
    pty.spawn('any_child_process', [/*any arguments*/], {
      name: 'xterm-color',
      cols: 80,
      rows: 30,
      cwd: process.cwd(),
      env: process.env
    });
    /*optionally you can install data handler
    term.on('data', function(data) {
      process.stdout.write(data);
    });
    term.write(.....);
    */

지금까지 UNIX v7에서 프로세스 시스템은 프로세스의 부모 ID를 확인함으로써 프로세스의 고아를 검출했습니다.으로, 가, 사 as, 사 as, 사 as는init(8)시스템 프로세스가 특별한 프로세스인 이유는 다음과 같습니다.그것은 죽을 수 없다.실행되었을 때 ID가 표시됩니다.exit(2)) 은 이 id.call(「」의 합니다).이를 통해 프로세스가 고립되었는지 여부를 알 수 있는 가장 쉽고 휴대성이 뛰어난 방법으로 테스트를 수행할 수 있습니다.해 주세요.getppid(2)콜 및 콜이 를 확인합니다.init(2)시스템 호출 전에 프로세스가 분리되었습니다.

이 접근방식에서는 다음 두 가지 문제가 발생하여 문제가 발생할 수 있습니다.

  • 먼저,먼저,.init모든 사용자 프로세스에 대한 프로세스입니다.그러면 어떻게 하면 초기 프로세스가 항상 모든 고아 프로세스의 부모가 될 수 있을까요? 그럼 .exit 프로세스인지 여부를 경우 패닉(할 수 ) 에서는 init 프로세스가 init을 할 수 .지 여부를 확인하기 위한 명시적 체크가 있습니다.그 경우 커널 패닉(프로세스 계층을 더 이상 유지할 수 없게 됩니다)이 있기 때문에 init 프로세스에서는 이 프로세스가 실행이 허용되지 않습니다.exit(2)discl.discl.discl을 클릭합니다.
  • 둘째, 위에서 드러난 기본 테스트에 인종 조건이 있습니다. process'으로 Init process' id로 됩니다.1ixix pos, POSIX pos pos pos pos pos pos pos pos pos pos pos pos pos pos pos pos pos.POSIX 어프로치에서는, 시스템의 프로세스 ID만이 그 목적을 위해서 예약되어 있습니다(다른 응답에 기재되어 있습니다).은 거의또, 원래의 에서는, posix 「」 「유닉스」 「」 「유닉스」 「유닉스」 「유닉스」 「유닉스」 「유닉스」 「유닉스」 「유닉스」 「유닉스」 「유닉스」 「유닉스」, 「유닉스」 「유닉스」를 가지는 것으로 할 수 .1의의 of of의 getppid(2)시스템 콜은 프로세스가 고립된 것으로 간주하기에 충분합니다. 하나의 은 VIP를 입니다.getppid(2)그 값을 새로운 콜의 결과와 비교합니다. 것은 때문에 모든 경우에하는 것은 또, 부모 는, 그 후에 할 수 .fork(2) 첫 '이행' 앞에getppid(2)시스템 콜을 실행합니다.parent id only changes once, when its parent does an syslog(2)call, so this should be enough to check if the (getppid (2)result changed between calls to see that parent process has exit. This test is not valid for the actual children of the init process, because they are always children of가 없는 할 수 process를 는 제외).init(8) 및 "init(init)"이 있습니다.

단말기 제어와 세션을 악용하여 3가지 공정으로 포터블 논폴링 솔루션을 할 수 있었습니다.

비결은 다음과 같습니다.

  • 프로세스 A가 시작됩니다.
  • 프로세스 A가 파이프 P를 작성합니다(이 프로세스에서 읽지 않음).
  • 프로세스 A를 프로세스 B로 분기하다
  • 프로세스 B가 새 세션을 만듭니다.
  • 프로세스 B는 새로운 세션에 가상 단말기를 할당합니다.
  • 프로세스 B는 자녀가 종료할 때 SIGCHLD 핸들러를 설치한다.
  • 프로세스 B는 SIGPIPE 핸들러를 설정합니다.
  • 프로세스 B를 프로세스 C로 분기합니다.
  • 프로세스 C는 필요한 모든 작업을 수행합니다(예를 들어 exec()는 변경되지 않은 바이너리 또는 임의의 로직을 실행합니다).
  • 프로세스 B가 파이프 P에 쓰기(및 그 방법으로 차단)
  • 프로세스 B의 프로세스A wait()가 정지하면 종료됩니다.

이 방법:

  • 프로세스 A가 정지한 경우: 프로세스 B가 SIGPIPE를 취득하여 정지합니다.
  • 프로세스 B가 정지한 경우: 프로세스 A의 wait()가 반환되어 정지된 경우 프로세스 C는 SAHUP를 취득합니다(단말기가 연결된 세션의 세션리더가 사망하면 포그라운드 프로세스 그룹 내의 모든 프로세스가 SAHUP을 취득하기 때문입니다).
  • 프로세스 C가 사망하는 경우: 프로세스 B가 SIGCHLD를 취득하여 사망하므로 프로세스 A가 사망합니다.

결점:

  • 프로세스 C가 SHEYUP을 처리할 수 없습니다.
  • 프로세스 C는 다른 세션에서 실행됩니다.
  • 프로세스 C는 세션/프로세스 그룹 API를 사용할 수 없습니다. 이는 취약한 설정이 중단되기 때문입니다.
  • 이러한 모든 작업을 위한 단말기를 만드는 것은 최고의 아이디어가 아니다

언급URL : https://stackoverflow.com/questions/284325/how-to-make-child-process-die-after-parent-exits

반응형