Chinaunix首页 | 论坛 | 博客
  • 博客访问: 521556
  • 博文数量: 51
  • 博客积分: 345
  • 博客等级: 民兵
  • 技术积分: 534
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-21 12:02
个人简介

文章分类

全部博文(51)

文章存档

2023年(2)

2022年(1)

2021年(7)

2020年(10)

2019年(2)

2016年(20)

2015年(5)

2014年(1)

2011年(3)

我的朋友

分类: C/C++

2016-08-22 15:41:40

源文件uloop.c

uloop_init

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


uloop_process_add

struct uloop_process

{

              struct list_head list;

              bool pending;    //成功加入链表的标志;

              uloop_process_handler cb;    //回调处理函数

              pid_t pid;    //fork出新进程的id号;

};

将当前uloop_process结构加入到processes双向列表,按照pid由小到大的顺序排列;最后置p->pending标记位为true

uloop_timeout_set

struct uloop_timeout

{

              struct list_head list;

              bool pending;    //成功加入链表的标志;

              uloop_timeout_handler cb;    //回调处理函数

              struct timeval time;    //超时时间

};

-->设置超时时间;

-->uloop_timeout_add     添加到timeouts列表;按照超时时间由小到大的顺序排列;

uloop_run


点击(此处)折叠或打开

  1. void uloop_run(void)
  2. {
  3.     static int recursive_calls = 0;
  4.     struct timeval tv;

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

  11.     uloop_cancelled = false;
  12.     while(!uloop_cancelled)
  13.     {
  14.         uloop_gettime(&tv);
  15.         uloop_process_timeouts(&tv);

  16.         if (do_sigchld)
  17.             uloop_handle_processes();

  18.         if (uloop_cancelled)
  19.             break;

  20.         uloop_gettime(&tv);
  21.         uloop_run_events(uloop_get_next_timeout(&tv));
  22.     }

  23.     if (!--recursive_calls)
  24.         uloop_setup_signals(false);
  25. }

-->static变量recursive_calls记录了是否该函数次数;若首次调用通过uloop_setup_signals设置信号处理函数;

         -->uloop_setup_signals

         SIGINTSIGTERMSIGCHLD设置处理函数,并记录了信号修改前的处理状态,以便之后恢复;

         SIGINTSIGTERM处理函数将全局变量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,并通过该pidprocesses链表内寻找对应节点,从链表中删除并执行其回调函数;

                   -->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_cancelledtrue时,才会break;也就是只有发送SIGINTSIGTERM信号时,才会退出循环;

uloop_done

-->关闭描述符poll_fd

-->清空timeoutsprocesses链表;
阅读(6087) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~