ev_child¶
关注进程状态变更
当您因为子进程状态变更而收到SIGCHLD的时候, 注册的ev_child则会触发.
在进入事件循环之前调用fork后注册ev_child, 然在运行事件循环期间就可以工作的很好. 但如果在运行时间循环期间fork后在注册ev_child则不行.
并且, 只有默认事件循环能够处理此信号, 因此只能在默认事件循环中注册ev_child。
进程的相互作用
一旦默认的事件循环初始化, Libev就能捕获到SIGCHILD. 即使第一个子进程退出后才启动ev_child, 这样中初始化顺序对保证正确性重要.
SIGCHLD的接收一定是异步的. 但是为了让其作为事件循环一部分, 进程状态获取则是同步的. Libev会接收到所有子进程的信号, 无论您是否关注它们的状态.
覆盖内置处理方法
Libev没有提供重写内置SIGCHILD处理的特殊支持, 虽然您可以通过自行注册SIGCHILD处理程序.
但是我建议您最好使用Libev基于事件的机制来处理, 这样您不必再为单独为它做额外的工作了.
停止ev_child
目前为止! 即使子进程终止或者退出ev_child也不会主动退出, 通常需要手动调用来停止运行.
但是在未来的版本可能会在检测的子进程退出后自动停止ev_child, 并且ev_child_stop调用多次不是问题.
相关函数¶
ev_child_init (ev_child *, callback, int pid, int trace);
// 配置ev_child观察pid指向的子进程ID的状态变化.
// 可以在回调函数里通过观察rstatus成员来查看状态(使用sys/wait.h中的宏并查看您的系统waitpid文档),
// rpid成员包含了导致变换的进程ID. trace则必须是0或者1.
// trace为0表示仅关注进程终止的状态.
// trace为1表示仅关注进程暂停、继续的状态.
ev_child_set (ev_child *, int pid, int trace);
// 表示关注的pid; 为0表示监视所有子进程.
int pid [read-only]
// 表示检测到状态变更的子进程ID.
int rpid [read-only]
// 导致的进程退出/跟踪状态.(更多内容请参阅sys/wait.h与waitpid的文档).
int rstatus [read-only]
示例¶
// 只需导入单个头文件
#include <ev.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// 当使用了键盘的组合键`CTRL`+`C`之后回调会被调用.
static void child_cb (struct ev_loop *loop, ev_child *w, int revents)
{
printf("Loop ot ProcessID: %d, Process status: %d\n", w->rpid, w->rstatus);
ev_break(loop, EVBREAK_ALL);
}
int main (void)
{
// 调用`fork`创建并分离父子进程
int id = fork();
if (id == -1) {
puts ("Failed to create child process.");
exit(EXIT_FAILURE);
}
// 如果id == 0就是子进程.
if (!id) {
sleep(1);
puts("Child process exit.");
exit(EXIT_SUCCESS);
}
// 可以使用已定义的宏来获取默认的事件循环, 当然你也可以根据自己的需求创建指定的.
struct ev_loop *loop = EV_DEFAULT;
ev_child child;
ev_child_init(&child, child_cb, 0, 0);
ev_child_start(loop, &child);
// 开始运行事件循环
ev_run (loop, 0);
// 如果事件循环退出, 那将会执行到这里.
return 0;
}