在打开管道以进行处理之后 popen, ,有没有办法杀死已经开始的过程? (使用 pclose 不是我想要的,因为那将等待该过程完成,但我需要杀死它。)

有帮助吗?

解决方案

不要使用popen(),然后写自己的包装器,可以做您想要的。

它对fork()非常简单,然后使用dup2()替换stdin&stdout,然后在孩子上调用exec()。

这样,您的父母将拥有确切的孩子PID,您可以在此使用Kill()。

Google搜索“ popen2()实现”,以获取有关如何实现Popen()所做的示例代码。只有十几行。摘自 dzone.com 我们可以看到一个看起来像这样的示例:

#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;
}

nb:似乎是您想要的popen2(),但是我的分布似乎并不是这种方法。

其他提示

这是Popen2的改进版本(信用归功于Sergey L.)。 Slacy发布的版本不会返回Popen2中创建的过程的PID,而是分配给的PID sh.

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};

Popen实际上并没有启动线程,而是叉一个过程。当我看一下定义时,看起来似乎没有一种简单的方法来获取该过程并杀死它。可能会有一些困难的方法,例如检查过程树,但是我想您最好使用管道,叉子和执行功能来模仿Popen的行为。然后,您可以使用从叉()获得的PID来杀死孩子的过程。

实际上,如果该过程正在执行I/O(应该是这样,否则为什么 popen 代替 system(3)?),然后 pclose 应该用一个 SIGPIPE 下次尝试阅读或写作时,应该很好地掉下来:-)

我遵循创建函数popen2的@slacy的想法。
但是在孩子过程死亡时发现了问题 outfp 不从功能返回。

可以通过在父进程上添加关闭未使用管道来解决。

close(p_stdin[READ]);
close(p_stdout[WRITE]);

我们可以通过使用bash作为外壳来获得正确的新过程的PID。

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

当孩子流程死亡时,功能的呼叫者 popen2 应该通过呼叫收集儿童进程状态 pclose2. 。如果我们不收集该状态的儿童进程可能是终止时的僵尸过程。

这是经过预期测试和工作的完整代码。

#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)
    {
        dup2(p_stdin[READ], STDIN_FILENO);
        dup2(p_stdout[WRITE], STDOUT_FILENO);

     //close unuse descriptors on child process.
     close(p_stdin[READ]);
     close(p_stdin[WRITE]);
     close(p_stdout[READ]);
     close(p_stdout[WRITE]);

        //can change to any exec* function family.
        execl("/bin/bash", "bash", "-c", command, NULL);
        perror("execl");
        exit(1);
    }

    // close unused descriptors on parent process.
    close(p_stdin[READ]);
    close(p_stdout[WRITE]);

    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;
}

int
pclose2(pid_t pid) {
    int internal_stat;
    waitpid(pid, &internal_stat, 0);
    return WEXITSTATUS(internal_stat);
}

显而易见的方法是系统(“ pkill process_name”);

显然,如果您的流程运行多个实例,这是有问题的。

我在Python做了类似的事情,您可以在那里杀死一个子过程和为此分配的任何子过程。实际上,这类似于Slacy的解决方案。http://www.pixelbeat.org/libs/subprocess.py

我只是将(Bash)脚本放入第一行中:

echo PID $$

然后我阅读了PID,然后使用它来做:杀死(PID,9)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top