打开管道到popen
的进程后,是否有办法终止已启动的进程? (使用pclose
不是我想要的,因为它会等待进程完成,但我需要杀死它。)
答案 0 :(得分:26)
不要使用popen(),并编写自己喜欢的包装器。
fork()相当简单,然后替换stdin&标准输出 通过使用dup2(),然后在您的孩子上调用exec()。
这样,您的父母将拥有确切的子PID,您可以使用 杀死()。
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;
}
注意:似乎popen2()就像你想要的那样,但我的发行版似乎没有这种方法。
答案 1 :(得分:5)
这是popen2的改进版本(信用归功于Sergey L.)。 slacy发布的版本不会返回在popen2中创建的进程的PID,而是返回分配给sh
的PID。
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};
答案 2 :(得分:4)
答案 3 :(得分:3)
实际上,如果流程正在进行I / O(应该是I / O,否则为什么popen
而不是system
(3)?),那么pclose
应该使用{ {1}}下次尝试读取或写入时,它应该很好地解决: - )
答案 4 :(得分:0)
显而易见的方法是system(“pkill process_name”);
如果您有多个进程实例正在运行,显然这是有问题的。
答案 5 :(得分:0)
我在python中做了类似的事情,在那里你可以杀死一个子进程和任何分叉的子进程。它实际上与slacy的解决方案类似。 http://www.pixelbeat.org/libs/subProcess.py
答案 6 :(得分:0)
我遵循创建函数popen2的@slacy的想法
但是当子进程死亡时发现问题,仍然读取文件描述符outfp
的父进程不从函数返回。
这可以通过在父进程上添加关闭unuse管道来解决。
close(p_stdin[READ]);
close(p_stdout[WRITE]);
我们可以使用bash作为shell来获得正确的新进程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);
}
答案 7 :(得分:0)
我只是在第一行输入(bash)脚本:
echo PID $$
然后我读了pid,并用它来做: 杀(PID,9)