cha*_*aos 26
没有什么比wait().通常的做法是使用轮询kill(pid, 0),寻找返回值-1和errno的ESRCH,表明进程已经一去不复返了.
Hon*_*gli 13
在BSD和OS X上,您可以使用带有EVFILT_PROC + NOTE_EXIT的kqueue来完成该操作.不需要投票.不幸的是,没有Linux等价物.
Dav*_*d Z 11
到目前为止,我已经在Linux上找到了三种方法:
kill或通过测试存在/proc/$pid,如在大多数其他答案中ptrace系统调用像调试器一样附加到进程,以便在退出时收到通知,如a3nm的答案netlink界面来监听PROC_EVENT_EXIT消息 - 这样每当进程退出时,内核就会告诉您的程序,而您只需等待正确的进程ID.我只在互联网上的一个地方看过这个.无耻的插件:我正在开发一个程序(当然是开源的; GPLv2),可以执行这三个程序中的任何一个.
您还可以创建套接字或FIFO并读取它们.FIFO特别简单:将您孩子的标准输出连接到FIFO并读取.读取将阻止,直到子进程退出(出于任何原因)或直到它发出一些数据.因此,您需要一个小循环来丢弃不需要的文本数据.
如果您可以访问子项的源,请在启动时打开FIFO进行写入,然后将其忘记.当子进程终止并且等待的"父"进程将被唤醒时,操作系统将清除打开的文件描述符.
现在这可能是一个你没有开始或拥有的过程.在这种情况下,您可以使用启动实际二进制文件的脚本替换二进制可执行文件,但也可以添加监视,如上所述.
这是一种等待 Linux 中的任何进程(不一定是子进程)退出(或被杀死)而不进行轮询的方法:
使用inotify等待/proc'pid'被删除将是完美的解决方案,但不幸的是inotify不适用于像/proc这样的伪文件系统。但是我们可以将它与进程的可执行文件一起使用。当该进程仍然存在时,该文件将保持打开状态。因此我们可以使用 inotify 和 IN_CLOSE_NOWRITE 来阻塞,直到文件关闭。当然,它可能会因其他原因而关闭(例如,如果具有相同可执行文件的另一个进程退出),因此我们必须通过其他方式过滤这些事件。
我们可以使用kill(pid, 0),但这不能保证它是否仍然是同一个进程。如果我们真的对此感到偏执,我们可以做点别的事情。
这是一种 100% 安全地防止 pid 重用问题的方法:我们打开伪目录 /proc/'pid',并保持它打开状态直到我们完成。如果同时使用相同的 pid 创建一个新进程,我们持有的目录文件描述符仍将引用原始进程(或者如果旧进程不再存在,则变得无效),但永远不会引用新进程重用的 pid。然后我们可以通过openat()检查目录中是否存在“cmdline”文件来检查原始进程是否仍然存在。当进程退出或被终止时,这些伪文件也不再存在,因此 openat() 将失败。
这是一个示例代码:
// return -1 on error, or 0 if everything went well
int wait_for_pid(int pid)
{
char path[32];
int in_fd = inotify_init();
sprintf(path, "/proc/%i/exe", pid);
if (inotify_add_watch(in_fd, path, IN_CLOSE_NOWRITE) < 0) {
close(in_fd);
return -1;
}
sprintf(path, "/proc/%i", pid);
int dir_fd = open(path, 0);
if (dir_fd < 0) {
close(in_fd);
return -1;
}
int res = 0;
while (1) {
struct inotify_event event;
if (read(in_fd, &event, sizeof(event)) < 0) {
res = -1;
break;
}
int f = openat(dir_fd, "fd", 0);
if (f < 0) break;
close(f);
}
close(dir_fd);
close(in_fd);
return res;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15238 次 |
| 最近记录: |