【Linux】浅谈eloop机制

您所在的位置:网站首页 cancel是干什么的 【Linux】浅谈eloop机制

【Linux】浅谈eloop机制

2024-06-04 06:20| 来源: 网络整理| 查看: 265

while (!eloop.terminate && (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || eloop.writers.count > 0 || eloop.exceptions.count > 0))

如果eloop.terminate变为非零值,就会退出循环。这是为了提供一种从外部结束循环的方法。例如 void eloop_terminate(void) 方法。 如果eloop.terminate为零,只要timeout链表或者任一个Socket不为空,都会继续循环。

select系统调用的原型是:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

关于select()函数的相关介绍,可见 select()函数用法

简单来讲:select函数可以同时监视多个文件描述符,并且可以监视三种事件。一旦某个文件描述符所指的对象发生了相应事件,就可以进行相应的处理。

在循环体里面:

(1)找到timeout链表的第一项(因为是按超时先后排序的,所以第一项肯定是最先超时的),计算超时时间距现在还有多久,并据此设置select的timeout参数。

(2)设置rfds,wfds和efds三个fd_set:方法是遍历各个eloop_sock_table,把每个sock描述符加入相应的fd_set里面。

(3)调用select。可能阻塞在此处。最大等待时间取决于“最快会发生的一次”timeout时间 。

(4)eloop_process_pending_signals(); 处理Signal事件。

(5)判断是否有timeout事件“超时”发生,如果是则调用其handler,并从timeout链表移除。然后继续下次循环。

(6)如果不是超时事件,则应该是rfds, wfds或者efds事件,fd_set里面会被改变,存放发生事件的描述符。因此分别遍历三个sock_table,如果其描述符在fd_set里面则调用其handler方法。

(7)继续下次循环。

我按循环中处理事件类型的先后顺序来分析  

4.1 signal事件 int eloop_register_signal(int sig, eloop_signal_handler handler, void *user_data) { struct eloop_signal *tmp; tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, sizeof(struct eloop_signal)); if (tmp == NULL) return -1; tmp[eloop.signal_count].sig = sig; tmp[eloop.signal_count].user_data = user_data; tmp[eloop.signal_count].handler = handler; tmp[eloop.signal_count].signaled = 0; eloop.signal_count++; eloop.signals = tmp; signal(sig, eloop_handle_signal); return 0; }

        别处调用 eloop_register_signal() 函数注册 signal 时,对应的 eloop_handle_signal 不会立即执行(初注册时将其 signaled置0)         只有当 signal 发生时才会将此 signal 的 signaled加1,表示此类 signal 已收到并处于 pending 状态(如何做到的呢?见 signal(sig, eloop_handle_signal); eloop_handle_signal 会将此 signal 的 signaled加1且eloop_data的signaled加1)        signal()函数用法见 signal()用法

      在select()超时或者有Socket事件方式时才会顺便调用eloop_process_pending_signals(), 对每个处于Pending状态的struct eloop_signal调用其handler。

4.2 socket事件

        在循环期间,外部调用 eloop_sock_table_add_sock() 函数往 eloop_sock_table 中添加 eloop_sock eloop_sock_table_set_fds() 函数将 rfds/wfds/efds 对应 sock位用 FD_SET 置1 而后调用 select() 函数

        select()返回值:发生错误时返回-1,超时时返回0。如果发生监视的事件,返回相应的文件描述符。         如果 select() 返回结果大于0,说明有socket事件发生,则调用 eloop_sock_table_dispatch() 依次处理三个 table(遍历三个table中的eloop_sock,调用其handler)

4.3 timeout事件

        eloop_date中维护一个 timeout 链表,按超时先后排序,依次处理

读者可自行把 eloop.c 和 eloop.h 中的一些 tool function读完。

可参考:

hostapd eloop初始化icon-default.png?t=N3I4https://www.cnblogs.com/xiaomingjun/p/16128774.html



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3