0

次のコードは、親プロセスが 10 秒間スリープしている間に、子プロセスとして "sleep 3" を fork して実行することを意図しています。親プロセスは、「スリープ 3」が終了した 3 秒後に SIGCHLD を受け取ることを期待しています。

これは起こらず、代わりに次のようになります。

main
parent process
parent sleeping for 10s
child process
child start, command: /bin/sleep, args: 0x7fffc68c8000, env: 0x7fffc68c8020

ps -efを示しています

chris    10578 10577  0 10:35 pts/25   00:00:00 /bin/sleep 3

続いて:

chris    10578 10577  0 10:35 pts/25   00:00:00 [sleep] <defunct>

次の 7 秒間 (この時点で親プロセスは終了します)。

問題は、clean_up_child_process決して呼び出されないことです。

私が犯した間違いは何ですか?

ゾンビテスト.c:

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <strings.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>

pid_t child_pid;

sig_atomic_t child_exit_status;

void clean_up_child_process (int signal_number) {
    printf("signal received\n");
    /* Clean up the child process. */
    int status;
    wait (&status);
    /* Store its exit status in a global variable. */
    child_exit_status = status;
    printf("child_exit_status %i\n", status);
}

int main(int argc, char **argv) {
    printf("main\n");

    int pid = fork();

    if (pid == 0) {
        printf("child process\n");
        signal(SIGCHLD, clean_up_child_process);

        char *args[] = { "/bin/sleep", "3", NULL };
        char *env[] = { NULL };
        printf("child start, command: %s, args: %p, env: %p\n", args[0], args, env);
        int ret = execve(args[0], args, env);

        // if we get here, then the execve has failed
        printf("exec of the child process failed %i\n", ret);
    } else if (pid > 0) {
        printf("parent process\n");
        child_pid = pid;
    } else {
        perror("fork failed\n");
    }
    printf("parent sleeping for 10s\n");
    sleep(10);
    return 0;
}
4

3 に答える 3

2

子プロセスが終了するのを待つように子プロセスに指示している場合、子プロセスは子プロセスを作成しない execve を呼び出していますが、代わりに現在のプログラムを実行中のプログラムに置き換えます

おそらく、親が子をインターセプトする必要があります (つまり、signal呼び出しを実行する前に呼び出しを行いforkます)。

于 2013-08-14T09:43:55.240 に答える
1

pid == 0見つかった: execve が呼び出されたときにそのプロセスが完全に置き換えられるため、signal への呼び出しはブランチにあるべきではありません。

シグナル呼び出しを の上に移動するとif、問題が解決します。

于 2013-08-14T09:42:32.093 に答える
0

この行: の代わりに signal(SIGCHLD, clean_up_child_process);書き込む必要があります(pid>0)(pid == 0)

SIGCHLDから参照してください:

SIGCHLDシグナルは、子プロセスが終了するとき、中断されるとき、または中断後に再開されるときに、子プロセスの親に送信されます。デフォルトでは、シグナルは単純に無視されます。

したがって、親は SIGCHLD を受け取り、親プロセスは clean_up_child_process を呼び出します。

于 2013-08-14T09:54:58.397 に答える