使用popen2创建的终止进程 [英] Killing process that has been created with popen2

查看:164
本文介绍了使用popen2创建的终止进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用函数popen2(在stackoverflow的其他地方建议使用此函数)以编程方式创建一个必须在一段时间后再次终止的进程. popen2返回一个PID,我认为该PID可用于终止进程.但是,这种方式行不通.为了杀死它,我必须增加返回的PID,我不理解(请参见下面的代码)

I'm using the function popen2 (that has been recommended elsewhere on stackoverflow) to programatically create a process that has to be killed again after some time. popen2 returns a PID and I thought that this PID could be used to kill the process. It doesn't work this way, though. In order to kill it, I have to increment the returned PID, which I don't understand (see code below)

当各种线程并行执行此操作时,可能会出现另一个问题.我认为,在那种情况下,PID可能会因比赛条件而相差一个以上.

Another problem might arise when various threads are doing this in parallel. In that case the PIDs might differ by more than one due to race conditions, I think.

所以我的问题是:在多线程情况下,如何可靠地标识popen2创建的进程的PID?

So my question is this: How can I reliably identify the PID of the process created by popen2 in a multi-threaded scenario?

#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>

#define READ 0
#define WRITE 1

pid_t popen2(const char *command, int *infp, int *outfp) {

    int p_stdin[2], p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
        return -1;

    pid = fork();

    if (pid < 0)
        return pid;
    else if (pid == 0)
    {
        close(p_stdin[WRITE]);
        dup2(p_stdin[READ], READ);
        close(p_stdout[READ]);
        dup2(p_stdout[WRITE], WRITE);

        execl("/bin/sh", "sh", "-c", command, NULL);
        perror("execl");
        exit(1);
    }

    if (infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    if (outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];

    return pid;
}

main() {
    pid_t pid;

    // Create process
    pid = popen2("crafty", &in, &out);

    sleep(5);

    // Why doesn't kill(pid, SIGKILL) work?
    kill(pid+1, SIGKILL);

    while (1); 
}

推荐答案

我想我明白了.

execl("/bin/sh", "sh", "-c", command, NULL);

运行sh,而popen2返回它的pid.当您调用kill时,它会杀死sh,但不会触及它的子进程command.杀死下一个pid杀死command实际上是actually幸.这并不总是可行,仅取决于比赛条件.

runs sh and popen2 returns it's pid. When you call kill it kills sh, but does not touch it's child process command. It is actually a fluke that killing the next pid kills command. This will not always work and is just up to race conditions.

如果您想终止目标进程,则必须直接启动它.

If you want to be able to kill your target process then you will have to start that directly.

警告(未经测试的代码):

Warning (untested code):

pid_t popen2(const char **command, int *infp, int *outfp) {

    int p_stdin[2], p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
        return -1;

    pid = fork();

    if (pid < 0)
        return pid;
    else if (pid == 0)
    {
        close(p_stdin[WRITE]);
        dup2(p_stdin[READ], READ);
        close(p_stdout[READ]);
        dup2(p_stdout[WRITE], WRITE);

        execvp(*command, command);
        perror("execvp");
        exit(1);
    }

    if (infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    if (outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];

    return pid;
}

并以

char *command[] = {"program", "arg1", "arg2", ..., NULL};

在您的特定示例中:

char *command[] = {"crafty", NULL};

这篇关于使用popen2创建的终止进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆