对于子进程,可以使用wait()
和waitpid()
函数来暂停当前进程的执行,直到子进程退出。但是这些函数不能用于非子进程。
是否有另一个函数可以等待任何进程的退出?
没有与wait()
相当的操作。通常的做法是使用kill(pid, 0)
进行轮询,并查看返回值为-1和errno
为ESRCH
来表示进程已经退出。
更新:自Linux内核5.3以来,引入了pidfd_open系统调用,它可以为给定的pid创建文件描述符,可以轮询该描述符获取pid退出时的通知。
在BSD和OS X上,您可以使用带有EVFILT_PROC+NOTE_EXIT的kqueue来完美实现此功能,无需轮询。不幸的是,Linux没有类似的功能。
// 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;
}
/proc/PID/exe
通常指向文件系统上的脚本或可执行文件,任何其他进程访问相同的文件都会触发inotifywait
!!请查看我的答案。 - F. Hauri - Give Up GitHubptrace(2)
附加到进程。从shell中,strace -p PID >/dev/null 2>&1
似乎可行。这样���以避免繁忙等待,虽然会减慢被跟踪的进程,并且不适用于所有进程(仅适用于您自己的进程,比仅适用于子进程好一点)。也许可以等待/proc/[pid]或/proc/[pid]/[something]消失?
有poll()和其他文件事件等待函数,也许可以帮助解决问题?
PR_SET_PDEATHSIG 可以用于等待父进程终止
我不知道还有其他的解决方案。除了混沌的解决方案,如果你可以更改要等待的程序,你可以使用信号量。
库函数包括sem_open(3)
、sem_init(3)
、sem_wait(3)
...
sem_wait(3)
执行等待操作,因此你不必像混沌的解决方案那样进行忙等待。当然,使用信号量会使你的程序更加复杂,这可能不值得麻烦。
kill()
之后,你应该使用usleep()
暂停一段时间。然后你必须在轮询的繁忙程度和进程消失前需要多长时间才能注意到之间取得平衡。 - chaosusleep()
已经过时了。现在似乎应该使用nanosleep()
代替它。 - chaoskill(pid,0)
会向你感兴趣的进程发送信号。在你调用nanosleep
期间,它可能已经死亡并被另一个正在运行的进程替代。我不需要更详细地解释了:已经提出了三个好建议(FIFO,信号量和ptrace
方法,在我看来,尽管非常特定于平台,但优于其他所有方法)。 - sam hocevar