打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
libubox

参考:libubox组件(3)——uloop

uloop是提供事件驱动机制接口,类似libevent事件框架,基于epoll接口来实现的。

uloop三大功能:事件管理(uloop_fd)、超时管理(uloop_timeout)和进程管理(uloop_process),定义在uloop.h中。

1. 整体框架

   1:  /**   2:   * 初始化事件循环   3:   *主要工作是poll_fd = epoll_create(32);/* 创建一个epoll的文件描述符监控句柄。最多监控32个文件描述符    4:   **/   5:  int uloop_init(void)   6:  {   7:      if (poll_fd >= 0)   8:          return 0;   9:     10:      poll_fd = epoll_create(32);/* 创建一个epoll的句柄。最多监控32个文件描述符 */  11:      if (poll_fd < 0)  12:          return -1;  13:     14:      fcntl(poll_fd, F_SETFD, fcntl(poll_fd, F_GETFD) | FD_CLOEXEC); /* fd_cloexecs */  15:      return 0;  16:  }  17:     18:     19:  /**  20:   * 事件循环主处理入口  21:   *1.当某一个进程第一次调用uloop_run时,注册sigchld和sigint信号  22:   *2.循环获取当前时间,把超时的timeout处理掉,有一条timeout链表在维护  23:   *3.循环检测是否收到一个sigchld信号,如果收到,删除对应的子进程,有一条process子进程链表在维护  24:   *4.循环调用epoll_wait 监相应的触发事件文件描述符fd   25:   **/  26:  void uloop_run(void)  27:  {  28:      static int recursive_calls = 0; /* static value */  29:      struct timeval tv;  30:     31:      /*  32:       * Handlers are only updated for the first call to uloop_run() (and restored  33:       * when this call is done).  34:       */  35:      if (!recursive_calls++) /* 第一次运行uloop_run时调用, 注册信号处理函数 */  36:          uloop_setup_signals(true);  37:     38:      uloop_cancelled = false;  39:      while(!uloop_cancelled)  40:      {  41:          uloop_gettime(&tv); /* 获取当前时间 */  42:          uloop_process_timeouts(&tv); /* 把超时的timeout清理掉 */  43:          if (uloop_cancelled)  44:              break;  45:     46:          if (do_sigchld) /*  收到一个sigchld的信号 */  47:              uloop_handle_processes(); /* 销毁该进程的uloop_process */  48:          uloop_gettime(&tv);  49:          uloop_run_events(uloop_get_next_timeout(&tv));/* 处理相应的触发事件fd */  50:      }  51:     52:      if (!--recursive_calls)  53:          uloop_setup_signals(false);  54:  }  55:     56:     57:  /**  58:   * 销毁事件循环  59:   * 关闭epoll描述符  60:   * 销毁子进程链表  61:   * 销毁timeout链表  62:  **/  63:  void uloop_done(void)  64:  {  65:      if (poll_fd < 0)  66:          return;  67:     68:      close(poll_fd);  69:      poll_fd = -1;  70:     71:      uloop_clear_timeouts();  72:      uloop_clear_processes();  73:  }
// 设置uloop内部结束循环标志static inline void uloop_end(void){    uloop_cancelled = true;}
int uloop_init(void);
void uloop_run(void);
void uloop_done(void);

2. uloop_fd

uloop是一个I/O循环调度,将不同文件描述符添加到轮询中。

文件描述符fd的管理由uloop_fd结构来设置。仅需设置fd和事件发生时的回调函数,数据结构的其他部分供内部使用。

默认采用非阻塞和水平触发。

#define ULOOP_READ      (1 << 0)#define ULOOP_WRITE     (1 << 1)#define ULOOP_EDGE_TRIGGER  (1 << 2)#define ULOOP_BLOCKING      (1 << 3)#define ULOOP_EVENT_MASK    (ULOOP_READ | ULOOP_WRITE)/* internal flags */#define ULOOP_EVENT_BUFFERED    (1 << 4)#ifdef USE_KQUEUE#define ULOOP_EDGE_DEFER    (1 << 5)#endif#define ULOOP_ERROR_CB      (1 << 6)struct uloop_fd{    uloop_fd_handler cb;    int fd;    bool eof;    bool error;    bool registered;    uint8_t flags;};int uloop_fd_add(struct uloop_fd *sock, unsigned int flags);int uloop_fd_delete(struct uloop_fd *sock);
typedef void (*uloop_fd_handler)(struct uloop_fd *u, unsigned int events);

 

3. uloop_timeout

超时管理部分由uloop_timeout结构来管理,在定时时间到了之后调用回调函数,定时时间单位为毫秒。

uloop定时器是一次性定时器,超时后会自动删除。

libubox使用一个全局排序链表(按照超时时间升序排列)存储定时器节点。

注:uloop将定时器节点按照绝对时间升序排,每次uloop循环先处理已超时的定时器,然后取定时器队列首节点(即最近一个将要超时的定时器节点),减去当前时间得到下次将要超时的相对时间;

然后用这个相对时间作为超时时间调用epoll_wait。

struct uloop_timeout{    struct list_head list;    bool pending;    uloop_timeout_handler cb;    struct timeval time;};int uloop_timeout_add(struct uloop_timeout *timeout);int uloop_timeout_set(struct uloop_timeout *timeout, int msecs);int uloop_timeout_cancel(struct uloop_timeout *timeout);int uloop_timeout_remaining(struct uloop_timeout *timeout);

typedef void (*uloop_timeout_handler)(struct uloop_timeout *t)

uloop_timeout_add()添加定时器,要求已初始化timeout结构,应避免直接使用uloop_timeout_add()。

uloop_timeout_set()设定定时器超时事件为当前时间+指定超时时间(msecs)。内部封装了uloop_timeout_add(),应调用本函数添加定时器。

4. uloop_process

当前进程的子进程管理。建立一个链表,按进程号升序方式管理所有进程id。

uloop进程管理是一次性任务,触发后会自动删除。

struct uloop_process{    struct list_head list;    bool pending;    uloop_process_handler cb;    pid_t pid;};int uloop_process_add(struct uloop_process *p);int uloop_process_delete(struct uloop_process *p);

typedef void (*uloop_process_handler)(struct uloop_process *c, int ret)

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
select、poll、epoll的比较
Linux中select poll和epoll的区别
【原创】技术系列之 网络模型(三)多路复用模型
libevent事件处理框架分析
Spice工作原理及代码剖析:02 Spice网络事件处理模型
Linux高级I/O
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服