libubox-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的更多相关文章
- libubox组件(3)——uloop
一:uloop概述 uloop有三个功能: 文件描述符触发事件的监控, timeout定时器处理, 当前进程的子进程的维护 二: uloop的整体框架 1: /** 2: * 初始化事件循环 3: ...
- libubox
lbubox是openwrt的一个核心库,封装了一系列基础实用功能,主要提供事件循环,二进制格式处理,linux链表实现和一些JSON辅助处理. 它的目的是以动态链接库方式来提供可重用的通用功能,给其 ...
- ubus
openwrt提供了一个系统总线ubus,类似linux桌面操作系统的d-bus,目标是提供系统级的进程间通信(IPC)功能. 为了提供各种后台进程和应用程序之间的通信机制,ubus被开发出来,由3部 ...
- openWrt libubox组件之uloop原理分析
1. libubox概述 libubox是openwrt新版本中的一个基础库,有很多应用是基于libubox开发的,如uhttpd,netifd,ubusd等. libubox主要提供以下两种功 ...
- libubox组件(1)——usock
一:相关API介绍 1.相关源码文件:usocket.h usocket.c 2.类型标志 1: #define USOCK_TCP 0 2: #define USOCK_UDP 1 3: #defi ...
- 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 ...
- tr069开源协议EasyCwmp移植
1.平台MT7628 2.交叉编译器及版本信息mipsel-linux + buildroot-gcc463_32bits.tar.bz2 3.创建工作目录lancer@ubuntu:~$ mkdir ...
- openwrt procd启动流程和脚本分析
Linux内核执行start_kernel函数时会调用kernel_init来启动init进程,流程如下图: graph LR A[start_kernel] -->B(rest_init) B ...
- libubox-runqueue
参考:libubox [4] - uloop runqueue ustream 任务队列是通过uloop定时器实现,把定时器超时时间设置为1,通过uloop事件循环来处理定时器就会处理任务队列中的ta ...
- libubox-ustream
参考:libubox [4] - uloop runqueue ustream libubox提供了流缓冲管理,定义在文件ustream.h,ustream.c和ustream-fd.c. 1. 数据 ...
随机推荐
- centos使用密钥替换密码登录服务器
一.首先登陆centos,切换用户,切换到你要免密码登陆的用户,进入到家目录,以下我以admin为例,命令:su admincd ~ 二.创建钥匙,命令:ssh-keygen -t rsa,一路按Y搞 ...
- Python datetime 格式化字符串:strftime()
Python datetime 格式化字符串:strftime() Python 的datetime模块 其实就是date和time 模块的结合, 常见的属性方法都比较常用 比如: datetim ...
- mount命令汇总
(一)挂接命令(mount) 首先,介绍一下挂接(mount)命令的使用方法,mount命令参数非常多,这里主要讲一下今天我们要用到的. 命令格式: mount [-t vfstype] [-o op ...
- urllib库在python2和python3环境下的使用区别
好东西啊!!! Python 2 name Python 3 name urllib.urlretrieve() urllib.request.urlretrieve() urllib.urlclea ...
- 转: Android中的签名机制
转载请注明出处:http://www.blogjava.net/zh-weir/archive/2011/07/19/354663.html Android APK 签名比对 发布过Android应用 ...
- [Algorithms] Build a Binary Tree in JavaScript and Several Traversal Algorithms
A binary tree is a tree where each node may only have up to two children. These children are stored ...
- 2014ACM/ICPC亚洲区域赛牡丹江现场赛总结
不知道怎样说起-- 感觉还没那个比赛的感觉呢?如今就结束了. 9号.10号的时候学校还评比国奖.励志奖啥的,由于要来比赛,所以那些事情队友的国奖不能答辩.自己的励志奖班里乱搞要投票,自己又不在,真是无 ...
- Discuz常见小问题2-如何修改管理员密码,修改admin账户密码
进入后台,点击用户,用户管理,搜索admin这个用户找到,然后点击详情 输入新密码即可(无需验证老的密码)
- 防止继承和覆盖(PHP类)
可能出现需求:我们不希望继承的类覆盖abstract类中的某个方法. 解决方案:我们可以在某个方法前面加上final关键词,可以防止继承的类覆盖它并实现继承类自己的版本. 继承类仍然可以访问和调用这些 ...
- 阻塞与非阻塞、同步与异步、I/O模型
1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步: 所谓同步,就是在c端 ...