如何在execv()执行进程时杀死C中的进程及其所有子进程?

moo*_*ara 3 c signals child-process

我正在尝试timeoutunix基于操作系统上实现类似命令,如下所示:

int                  pid;
timer_t              timer_id;
struct sigevent      timer_event;
struct itimerspec    timer_value;

void timeout_signal_handler(int sig_no)
{
    kill(pid, SIGKILL);
}

int create_timer()                        { /* implementation */ }
int start_timer_oneshot(int interval_ms)  { /* implementation */ }

int main(int argc, char* argv[])
{

    int   status, pid_return;
    void  *signal_return;

    if (argc < 2)
        return EXIT_FAILURE;

    signal_return = signal(SIGUSR1, timeout_signal_handler);
    if (signal_return == SIG_ERR)
        return EXIT_FAILURE;

    create_timer();
    start_timer_oneshot(TIMEOUT);

    if ((pid = fork()) == 0)
    {
        execv(argv[1], &argv[1]);
        return EXIT_FAILURE;
    }
    else
    {
        status = -1;
        while (status == -1)
            status = wait(&pid_return);
    }

    return EXIT_SUCCESS;

}
Run Code Online (Sandbox Code Playgroud)

我使用此实用程序如下:

./timeout example
Run Code Online (Sandbox Code Playgroud)

example程序运行几秒钟,并分叉几个进程.当计时器到期时timeout,只有父进程example被杀死并且其子进程在控制台上继续打印.

当我运行example没有timeout,并按下时Ctrl+C,父项及其所有子项都被成功杀死.

任何人都可以让我知道我怎么能在我的timeout程序中解决这个问题?

alk*_*alk 5

你想打电话kill()给pid 0.这会将信号发送给调用进程的进程组的所有成员.

然而,这仅在这个过程中,这一直工作fork()/ exec*()"ED(或其子女)本身并不改变其(他们的)进程组.

来自man 2 kill:

如果pid为0,则应将sig发送到进程组ID等于发送方的进程组ID且进程有权发送信号的所有进程(不包括未指定的系统进程集).

  • 请注意,它也表示超时过程.让孩子成为一个过程组领导者然后让父过程信号表明过程组是可行的(通过[`setpgid()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions /setpgid.html)).父级知道哪个进程组(它是与子级的PID具有相同编号的进程组ID),因此它可以将信号发送到子级PID的负数以指示子级进程组的信号. (2认同)