彻底理解 IO 多路复用实现机制( 三 )
(4)以tcp_poll为例 , 其核心实现就是__pollwait , 也就是上面注册的回调函数 。
(5)__pollwait的主要工作就是把current(当前进程)挂到设备的等待队列中 , 不同的设备有不同的等待队列 , 对于tcp_poll来说 , 其等待队列是sk->sk_sleep(注意把进程挂到等待队列中并不代表进程已经睡眠了) 。 在设备收到一条消息(网络设备)或填写完文件数据(磁盘设备)后 , 会唤醒设备等待队列上睡眠的进程 , 这时current便被唤醒了 。
(6)poll方法返回时会返回一个描述读写操作是否就绪的mask掩码 , 根据这个mask掩码给fd_set赋值 。
(7)如果遍历完所有的fd , 还没有返回一个可读写的mask掩码 , 则会调用schedule_timeout是调用select的进程(也就是current)进入睡眠 。 当设备驱动发生自身资源可读写后 , 会唤醒其等待队列上睡眠的进程 。 如果超过一定的超时时间(schedule_timeout指定) , 还是没人唤醒 , 则调用select的进程会重新被唤醒获得CPU , 进而重新遍历fd , 判断有没有就绪的fd 。
(8)把fd_set从内核空间拷贝到用户空间 。
select函数接口#include #include #define FD_SETSIZE 1024#define NFDBITS (8 * sizeof(unsigned long))#define __FDSET_LONGS (FD_SETSIZE/NFDBITS)// 数据结构 (bitmap)typedef struct {unsigned long fds_bits[__FDSET_LONGS];} fd_set;// APIint select(int max_fd,fd_set *readset,fd_set *writeset,fd_set *exceptset,struct timeval *timeout)// 返回值就绪描述符的数目FD_ZERO(int fd, fd_set* fds)// 清空集合FD_SET(int fd, fd_set* fds)// 将给定的描述符加入集合FD_ISSET(int fd, fd_set* fds)// 判断指定描述符是否在集合中 FD_CLR(int fd, fd_set* fds)// 将给定的描述符从文件中删除
select使用示例int main() {/** 这里进行一些初始化的设置 ,* 包括socket建立 , 地址的设置等,*/fd_set read_fs, write_fs;struct timeval timeout;int max = 0;// 用于记录最大的fd , 在轮询中时刻更新即可// 初始化比特位FD_ZERO(FD_ZERO(int nfds = 0; // 记录就绪的事件 , 可以减少遍历的次数while (1) {// 阻塞获取// 每次需要把fd从用户态拷贝到内核态nfds = select(max + 1,// 每次需要遍历所有fd , 判断有无读写事件发生for (int i = 0; i <= max++i) {if (i == listenfd) {--nfds;// 这里处理accept事件FD_SET(i, //将客户端socket加入到集合中}if (FD_ISSET(i,// 这里处理read事件}if (FD_ISSET(i,// 这里处理write事件}}}
select缺点select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理 。 这样所带来的缺点是:
- 单个进程所打开的FD是有限制的 , 通过 FD_SETSIZE 设置 , 默认1024 ;
- 每次调用 select , 都需要把 fd 集合从用户态拷贝到内核态 , 这个开销在 fd 很多时会很大;
- 对 socket 扫描时是线性扫描 , 采用轮询的方法 , 效率较低(高并发)
pollpoll本质上和select没有区别 , 它将用户传入的数组拷贝到内核空间 , 然后查询每个fd对应的设备状态 ,但是它没有最大连接数的限制 , 原因是它是基于链表来存储的.
poll函数接口
#include // 数据结构struct pollfd {int fd;// 需要监视的文件描述符short events;// 需要内核监视的事件short revents;// 实际发生的事件};// APIint poll(struct pollfd fds[], nfds_t nfds, int timeout);
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 曾被京东物流效仿,让雷军花1亿拯救,如今欠7000万彻底出局
- 线下市场彻底“乱了”!小米宣布新规!华为捆绑加价行为迎争议
- 一波未平一波又起,我买个菜就欠了一笔贷款?美团这次彻底没话说
- 微软|外媒:微软将对Windows 10界面进行彻底改进 已招兵买马
- 华为P50真机图曝光:外形变化很彻底
- 京东7FRESH迎来彻底变革
- Windows 10等软件全部封杀 Flash彻底说再见
- 数据|新基建时代,高大全的数据管理解决方案是怎样“炼”成的?
- 尼康相机将于2021年底前彻底告别“日本产”
- 微信的一项更新,彻底让用户“反感”,这是要开启直播时代?