Skip to content

Liu-YT/IO-Multiplexing

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

IO Multiplexing

select、poll、epoll

源码剖析

简单DEMO

原理概述

select

调用 select 函数

  1. 从用户空间拷贝 fd_set 到内核空间
  2. 注册回调函数 __pollwait
  3. 遍历所有 fd, 对全部指定设备做一次 poll(这里的 poll 是一个文件操作,它有两个参数,一个是文件 fd 本身,一个是当设备尚未就绪时调用的回调函数 __pollwait,这个函数把设备自己特有的等待队列传给内核,让内核把当前的进程挂载到其中)
  4. 当设备就绪时,设备就会唤醒在自己特有等待队列中的所有节点,于是当前进程就获取到了完成的信号,poll 文件操作返回的是一组标准的掩码,其中的各个位指示当前的不同的就绪状态(全0为没有任何事件触发),根据 mask 可对 fd_set 赋值
  5. 如何所有设备的返回的掩码都没有显示任何的事件触发,就去掉回调函数的函数指针,进入有限时的睡眠状态,再回复和不断做 poll,直到其中一个设备有事件触发为止
  6. 只要有事件触发,系统调用返回,将 fd_set 从内核空间拷贝到用户空间,回到用户态,用户可以对相关的 fd 作进一步的度或者写操作

epoll

调用 epoll_create 时

  1. 内核帮我们在 epoll 文件系统里建了个 file 结点
  2. 在内核 cache 里建了个红黑树用于存储以后 epoll_ctl 传来的socket
  3. 建立一个 list 链表,用于存储准备就绪的事件

调用 epoll_ctl 时

  1. 把 socket 放到 epoll 文件系统里 file 对象对应的红黑树上
  2. 给内核中断处理程序注册一个回调函数,告诉内核如果这个句柄的中断到了,就把它放到准备就绪 list 链表里

调用 epoll_wait 时

观察 list 链表里有没有数据,有数据就返回,没有数据就 sleep,等到 timeout 时间后即使链表没数据也返回。

总结

  • select的最大文件描述符的限制是1024(其描述符最大为1024,此处非数目),可以说其是受内部实现FD_SIZE的限制,仅可以通过修改内核重新编译实现修改,而pollepoll其实也是受进程的能打开的最大文件描述符数目限制,但是可以修改ulimit -n <数目>

相关基础博客

一些好的博客

About

select、poll、epoll

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published