procd系列五:uloop_run分析

源文件uloop.c

uloop_init

创建epoll句柄;并设置句柄FD_CLOEXEC属性;对描述符设置了FD_CLOEXEC,使用execl执行的程序里,此描述符被关闭,不能再使用它,但是在使用fork调用的子进程中,此描述符并不关闭,仍可使用。

uloop_run

void uloop_run(void)
{
    static int recursive_calls = 0;
    struct timeval tv;

    /*
     * Handlers are only updated for the first call to uloop_run() (and restored
     * when this call is done).
     */
    if (!recursive_calls++)
        uloop_setup_signals(true);

    uloop_cancelled = false;
    while(!uloop_cancelled)
    {
        uloop_gettime(&tv);
        uloop_process_timeouts(&tv);

        if (do_sigchld)
            uloop_handle_processes();

        if (uloop_cancelled)
            break;

        uloop_gettime(&tv);
        uloop_run_events(uloop_get_next_timeout(&tv));
    }

    if (!--recursive_calls)
        uloop_setup_signals(false);
}

  • static变量recursive_calls记录了是否该函数次数;若首次调用通过uloop_setup_signals设置信号处理函数;
  •  uloop_setup_signals对SIGINT、SIGTERM、SIGCHLD设置处理函数,并记录了信号修改前的处理状态,以便之后恢复;SIGINT、SIGTERM处理函数将全局变量uloop_cancelled 设置为true;SIGCHLD处理函数将全局变量do_sigchld设置为true;当子进程终止或停止时,将SIGCHLD信号发送给其父进程,系统默认忽略此信号;忽略SIGPIPE信号;
  • 接着进程会进入一个while循环来处理定时器和信号事件;
  • uloop_gettime获取当前系统时间;
  • uloop_process_timeouts(&tv); 遍历timeouts链表内节点,检测到存在当前时间点可以触发的事件则触发回调函数,并从链表中移除该事件;若运行期间存在SIGCHLD事件,则do_sigchld置为true,调用函数uloop_handle_processes处理首先将do_sigchld置为false,等待下次信号产生再激活该函数;调用waitpid来获取已经结束的子进程的PID,并通过该pid在processes链表内寻找对应节点,从链表中删除并执行其回调函数;uloop_gettime(&tv);再次获取当前时间;uloop_get_next_timeout(&tv)通过查找timeouts链表,计算下一个超时事件的时间间隔;若链表为空返回-1;若存在立刻应该触发的时间返回0;
  • uloop_get_next_timeout返回值作为uloop_run_events的入参,利用epoll_wait的超时机制来实现定时器的操作;epoll_wait超时返回则再次执行while循环;
  • uloop_run_events同时还监听已经注册到poll_fd内的描述符,通过返回的struct epoll_event events数组来判断发生的事件,并执行其cb函数;
  • while循环只有在uloop_cancelled为true时,才会break;也就是只有发送SIGINT、SIGTERM信号时,才会退出循环;
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值