FreeBSD Kqueue的实现原理

    kqueue/epoll 是两个网上出现频率比较高的关键字,epoll实现原理及源码网上已经有很多blog分析,关于
select/poll/epoll、kqueque的优缺点也不再解释。kqueue实现原理的文章网上资料比较少, 基本上就
Jonathan Lemon的一篇论文, Jonathan Lemon也是Kqueue的发明者。文章链接: 
Kqueue: A generic and scalable event notification facility 

    本文主要说明一下其中的kqueue的实现部分,从网络收发部分看kqueue和epoll的使用方式和实现原理都
比较类似.这篇文章介绍了kqueue的使用方法:使用 kqueue 在 FreeBSD 上开发高性能应用服务器
kqueue的是主要实现逻辑在kern_event.c 里面(freebsd 4.1)

      在kqueue实现中,比较关键的是一个knote结构体,该结构体在内核空间对应于应用层的kevent结构体.  
knote将事件源(被监控节点tcp/socket), 事件源是否有事件发生和knote所在的kqueue联系起来.  knote
之间也有联系这个后面具体分析.另一个比较关键的数据结构是kqueue自己,包含两个功能:1)包含一个有
事件发生需要通知应用层的knotes队列,也就是已完成事件队列. 2) 保存并跟踪应用层注册的的需要监听
的事件和描述符.kqueue有三个子结构体来实现上面的功能:
        --1. 一个队列,用来保存active的knotes节点
        --2. 一个小hashtable 用来查找那些没有对应描述符的knotes节点
        --3, 一个线性的描述符array,这个array和进程打开的文件描述符表一致

    上述的hashtable 和线性数组都是延迟分配的,  存放描述符array可以自动扩展, kqueue必须记录这些所
有用户注册的knotes, 当kqueue被close,属于它的knotes都会被释放. 描述符array可以保证当用用户关闭一
个描述符如(socket fd)时, kqueue对应的knotes 节点会别释放.


事件注册:
    最初, 应用程序调用kqueue() 来分配一个新的kqueue(一下简称KQ), 涉及到了分配一个新的kqueue描
述符、kqueue结构体、和一个指向已打开文件描述符table的指针, 这个时候并没有给这个给array和
hashtable分配空间.应用然后调用kevent()传递一个changelist指针(参见kevent使用说明),changelist
中的kevents从用户空间copy到内核空间, 然后对每一个kevents调用register().  register()先在KQ中
查找是否有匹配的knotes, 如果过没有,表明第一次添加,分配一个新的knotes(有EV_ADD标记).根据传递来
的kevent信息对新建的knotes进行初始化,并调用attacth()将knote连接到事件源(如tcp收包).这个连接操
作是通过一个叫filter(不明白为啥叫filter)的attach函数.  之后将knote添加到KQ的hashtable或array
中.如果在处理changelist发生错误, 发生错误的kevent则会copy到evenlist返回给应用层.当changelist
的所有事件都处理成功后 kqueue_scan()才会开始检查是否有active的事件.

Filters:
    每一个filter都包含三个函数{attach, detach, filter},filter根据事件源类型决定(如tcp/udp/file分别有自己的filter)
      --attach() :    将knote加入到要监听的事件源中.
      --deattch():   将knote从某一事件源中取消.
      --filter():     当事件源(TCP)有事件发生时,如收到数据会先调用该函数先检查当前事件
                           是否需要通知到应用层.  filter()返回boolean类型表明事件是否需要通知应用层.
                           kqueue_sacn()也会调用该函数来检测某一事件是否已满足

      跟事件源连接,事件源是否有事件发生,发生时通知哪些knotes节点, 都通过这三个函数来实现.

事件源有事件发生:
    当有事件发生时(收到一个数据包、文件被修改、一个进程退出),最终会将事件通知给应用层. 收到事
件时事件源会对attach到自己的knotes链表调用knote()函数.knote()扫描所有link到该事件源的knotes,
检测事件是否满足通知条件(filter()函数).如果事件条件满足则将该knote放入到kqueue的active list队
列里,最终会传递给应用层.

投递:
    主要将kqueue active list里的事件copy到应用层
下面是调用栈示简单示意图(freebsd 4.1 ),以TCP为例:

[cpp]  view plain copy
  1. //***************************************************************************    
  2.     
  3. //注册    
  4. kevent()    
  5.   ->kqueue_register()  //注册要监听的TCP的事件    
  6.     ->knote_attach      //分配note结点,并和相对应的socket 连接    
  7.     ->fops->f_attach()==filt_sorattach()  //调用TCP socketfilter里的attach函数    
  8.        ->SLIST_INSERT_HEAD()   // 将knotes结点挂入该socket的knotes 列表    
  9.            
  10.     
  11. //检测是否有event发生    
  12. kevent()    
  13.   ->kqueue_scan()  // 检查是否有时间按发生     
  14.     ->tsleep()      //事件为空则sleep 等待事件通知    
  15.             
  16.     
  17. //TCP 收报流程    
  18. tcp_input()    
  19.   ->sowwakeup()    
  20.     ->sowakeup()        
  21.       ->knote()   //遍历连接到自己的knotes结点list    
  22.         ->kn_fop->f_even()  //事件满足唤醒条件    
  23.         ->knote_enqueue()    //将knote插入kqueue的active队列    
  24.           ->wakeup();   //唤醒kqueue    
  25.     
  26. //************************************************************************  


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeBSD操作系统设计与实现》是一本介绍FreeBSD操作系统的权威性书籍。该书籍全面解析了FreeBSD操作系统的设计原理实现细节,深入讲解了FreeBSD操作系统的核心概念、功能模块和体系结构。 《FreeBSD操作系统设计与实现》一书主要分为五个部分:系统概述、进程管理、存储管理、文件系统和设备驱动。每个部分都对应着FreeBSD操作系统的一个重要方面,详细介绍了相应的设计原理实现方式。 在系统概述部分,该书首先对FreeBSD操作系统的历史背景、发展过程和基本特性进行了介绍。然后,深入剖析了FreeBSD操作系统的体系结构,包括内核模块的组织结构、进程通信机制、虚拟内存管理和网络子系统等。 在进程管理部分,该书详细讨论了FreeBSD操作系统的进程管理机制,包括进程的创建、调度与退出,进程间的通信和同步方法,以及线程管理和多核支持等。 存储管理部分着重介绍了FreeBSD操作系统的存储管理机制。主要包括物理内存管理、页表管理、虚拟内存系统和缓存管理等内容。同时,该书还对FreeBSD中常用的文件系统如UFS和ZFS进行了深入讲解。 在文件系统部分,该书介绍了FreeBSD操作系统的文件系统层次结构、文件系统缓存和文件系统的操作接口。同时,还讨论了FreeBSD中的文件系统实现原理和常用的文件系统类型。 最后,设备驱动部分详细说明了FreeBSD操作系统的设备管理机制和驱动框架。该书介绍了设备驱动的注册、初始化和操作方式,并讨论了常见设备的驱动实现方法。 总之,《FreeBSD操作系统设计与实现》是一本全面系统地介绍FreeBSD操作系统的权威书籍。它对FreeBSD操作系统的设计原理实现细节进行了深入剖析,对于对操作系统设计和实现有兴趣的读者来说是一本非常有价值的参考资料。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值