WPA_SUPPLICANT源码分析(1):EVENT LOOP的实现 (转)

WPA_SUPPLICANT的程序的生命就是在运行一个EVENT LOOP, 等待各种Event的到来,然后做相应的处理。因此分析EVENT LOOP的实现能起到提纲挈领的作用。


1. 数据结构: 见下图



struct eloop_data结构体是一个统领全局的数据结构,只有一个实例,即Line 75:

点击(此处)折叠或打开

  1. static struct eloop_data eloop;
要处理的Event有三大种类型:Socket事件,Timeout事件,Signal事件.  其中Socket事件又分为三种类型:

  1.  * @EVENT_TYPE_READ: Socket has data available for reading
  2.  * @EVENT_TYPE_WRITE: Socket has room for new data to be written
  3.  * @EVENT_TYPE_EXCEPTION: An exception has been reported
Socket 事件:有readers, writers, exceptions三个eloop_sock_table结构体, 每个里面都有动态数组,数组的每一项都是一个具体的eloop_sock.  可以向各个Table里面添加、删除eloop_sock.  事件分发就是遍历sock_table, 依次运行里面的每个Handler.

Timeout事件: 每个struct eloop_timeout都被放在一个双向链表中, 链表头就是eloop_data中的”timeout”项。这些struct eloop_timeout按超时先后排序。

Signal事件:每个struct eloop_signal放在动态数组中

疑问: 为什么Socket和signal事件不使用链表,而是动态的扩大和缩小数组?

2. 基于Select的多Event处理

void eloop_run(void) 是个总函数,我们看它是怎么用select系统调用实现多路复用监听多个事件的。

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

如果eloop.terminate变为非零值,就会退出循环。这是为了提供一种从外部结束循环的方法。

如果eloop.terminate为零,只要timeout链表或者任一个Socket不为空,都会继续循环。

Select系统调用的原型是:

  1. int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
在循环体里面:

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

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

(3)调用select。   可能阻塞在此处。

(4)eloop_process_pending_signals();  处理Signal事件。后面会分析。

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

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

(7)继续下次循环.

值得一提的是,这里对Signal的处理有点特别。在eloop_register_signal() 函数注册的signal的Handler并不是当Signal发生时就会自动执行的。当Signal发生时只会对该struct eloop_signal的 signaled变量加1,以表明Signal已收到并处于Pendning状态。在select()超时或者有Socket事件方式时才会顺便调用eloop_process_pending_signals(), 对每个处于Pending状态的struct eloop_signal调用其Handler.

疑问:这样做有什么好处?如果select阻塞很久,岂不是Signal也要Pending很久才得到处理?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值