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

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

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

1. 整体框架

   :  /**

   2:   * 初始化事件循环

   3:   *主要工作是poll_fd = epoll_create(32);/* 创建一个epoll的文件描述符监控句柄。最多监控32个文件描述符 

   4:   **/

   :  int uloop_init(void)

   :  {

   :      if (poll_fd >= )

   :          return ;

   :   

  :      poll_fd = epoll_create();/* 创建一个epoll的句柄。最多监控32个文件描述符 */

  :      if (poll_fd < )

  :          return -;

  :   

  :      fcntl(poll_fd, F_SETFD, fcntl(poll_fd, F_GETFD) | FD_CLOEXEC); /* fd_cloexecs */

  :      return ;

  :  }

  :   

  :   

  :  /**

  20:   * 事件循环主处理入口

  21:   *1.当某一个进程第一次调用uloop_run时,注册sigchld和sigint信号

  22:   *2.循环获取当前时间,把超时的timeout处理掉,有一条timeout链表在维护

  23:   *3.循环检测是否收到一个sigchld信号,如果收到,删除对应的子进程,有一条process子进程链表在维护

  24:   *4.循环调用epoll_wait 监相应的触发事件文件描述符fd 

  25:   **/

  :  void uloop_run(void)

  :  {

  :      static int recursive_calls = ; /* static value */

  :      struct timeval tv;

  :   

  :      /*

  32:       * Handlers are only updated for the first call to uloop_run() (and restored

  33:       * when this call is done).

  34:       */

  :      if (!recursive_calls++) /* 第一次运行uloop_run时调用, 注册信号处理函数 */

  :          uloop_setup_signals(true);

  :   

  :      uloop_cancelled = false;

  :      while(!uloop_cancelled)

  :      {

  :          uloop_gettime(&tv); /* 获取当前时间 */

  :          uloop_process_timeouts(&tv); /* 把超时的timeout清理掉 */

  :          if (uloop_cancelled)

  :              break;

  :   

  :          if (do_sigchld) /*  收到一个sigchld的信号 */

  :              uloop_handle_processes(); /* 销毁该进程的uloop_process */

  :          uloop_gettime(&tv);

  :          uloop_run_events(uloop_get_next_timeout(&tv));/* 处理相应的触发事件fd */

  :      }

  :   

  :      if (!--recursive_calls)

  :          uloop_setup_signals(false);

  :  }

  :   

  :   

  :  /**

  58:   * 销毁事件循环

  59:   * 关闭epoll描述符

  60:   * 销毁子进程链表

  61:   * 销毁timeout链表

  62:  **/

  :  void uloop_done(void)

  :  {

  :      if (poll_fd < )

  :          return;

  :   

  :      close(poll_fd);

  :      poll_fd = -;

  :   

  :      uloop_clear_timeouts();

  :      uloop_clear_processes();

  :  }
// 设置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。


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)

libubox-uloop的更多相关文章

  1. libubox组件(3)——uloop

    一:uloop概述 uloop有三个功能: 文件描述符触发事件的监控,  timeout定时器处理, 当前进程的子进程的维护 二: uloop的整体框架 1: /** 2: * 初始化事件循环 3: ...

  2. libubox

    lbubox是openwrt的一个核心库,封装了一系列基础实用功能,主要提供事件循环,二进制格式处理,linux链表实现和一些JSON辅助处理. 它的目的是以动态链接库方式来提供可重用的通用功能,给其 ...

  3. ubus

    openwrt提供了一个系统总线ubus,类似linux桌面操作系统的d-bus,目标是提供系统级的进程间通信(IPC)功能. 为了提供各种后台进程和应用程序之间的通信机制,ubus被开发出来,由3部 ...

  4. openWrt libubox组件之uloop原理分析

    1.    libubox概述 libubox是openwrt新版本中的一个基础库,有很多应用是基于libubox开发的,如uhttpd,netifd,ubusd等. libubox主要提供以下两种功 ...

  5. libubox组件(1)——usock

    一:相关API介绍 1.相关源码文件:usocket.h usocket.c 2.类型标志 1: #define USOCK_TCP 0 2: #define USOCK_UDP 1 3: #defi ...

  6. libubox组件(2)——blob/blobmsg (转载 https://segmentfault.com/a/1190000002391970)

    一:blob相关接口 1.数据结构 1: struct blob_attr { 2: uint32_t id_len; /** 高1位为extend标志,高7位存储id, 3: * 低24位存储dat ...

  7. tr069开源协议EasyCwmp移植

    1.平台MT7628 2.交叉编译器及版本信息mipsel-linux + buildroot-gcc463_32bits.tar.bz2 3.创建工作目录lancer@ubuntu:~$ mkdir ...

  8. openwrt procd启动流程和脚本分析

    Linux内核执行start_kernel函数时会调用kernel_init来启动init进程,流程如下图: graph LR A[start_kernel] -->B(rest_init) B ...

  9. libubox-runqueue

    参考:libubox [4] - uloop runqueue ustream 任务队列是通过uloop定时器实现,把定时器超时时间设置为1,通过uloop事件循环来处理定时器就会处理任务队列中的ta ...

  10. libubox-ustream

    参考:libubox [4] - uloop runqueue ustream libubox提供了流缓冲管理,定义在文件ustream.h,ustream.c和ustream-fd.c. 1. 数据 ...

随机推荐

  1. Vue-router路由基础总结(二)

    一.命名路由 有时我们通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候.你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称. 我 ...

  2. Documentation/ABI/testing/sysfs-block.txt

    Chinese translated version of Documentation/ABI/testing/sysfs-block.txt If you have any comment or u ...

  3. 用好Git 和 SVN,轻松驾驭版本管理

    用好Git 和 SVN,轻松驾驭版本管理 本文从 Git 与 SVN 的对比入手,介绍如何通过 Git-SVN 开始使用 Git,并总结平时工作高频率使用到的 Git 常用命令. 一.Git vs S ...

  4. ElasticSearch reindex报错:the final mapping would have more than 1 type

    ElasticSearch reindex报错:the final mapping would have more than 1 type 学习了:https://blog.csdn.net/qq_2 ...

  5. 【ACM】最小公倍数

    http://acm.hdu.edu.cn/game/entry/problem/show.php?chapterid=2&sectionid=1&problemid=1 #inclu ...

  6. docker学习笔记二:常用命令

    docker学习笔记二:常用命令 查看docker常用命令 docker --help 返回结果如下: 其中常用的命令如下: 1.image相关操作 展示所有的image: 删除image: rmi ...

  7. 在Lucene或Solr中实现高亮的策略

    一:功能背景 近期要做个高亮的搜索需求,曾经也搞过.所以没啥难度.仅仅只是原来用的是Lucene,如今要换成Solr而已,在Lucene4.x的时候,散仙在曾经的文章中也分析过怎样在搜索的时候实现高亮 ...

  8. python的__init__和__new__

    本文所有实例代码在python3.7下 一.__new__和__init__区别 1.__new__先于__init__执行;__new__是相当于其他OOP语言的构造方法,负责创建实例:之后,__i ...

  9. 算法笔记_105:蓝桥杯练习 算法提高 上帝造题五分钟(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 第一分钟,上帝说:要有题.于是就有了L,Y,M,C 第二分钟,LYC说:要有向量.于是就有了长度为n写满随机整数的向量 第三分钟,YUHC ...

  10. ant Select 联动

    1.代码 /** * 选择监区 组件 */ import React, { PureComponent } from 'react'; import PropTypes from 'prop-type ...