当前位置:网站首页>I/O多路复用及其相关详解
I/O多路复用及其相关详解
2022-04-23 17:54:00 【Augustu_】
Fd详解
Fd:是一个正整型数,实际是为文件描述符表(数组)的索引,文件描述符表中保存着已打开的文件的指针。
每一个进程在PCB(Process Control Block)即进程控制块中都保存着一分文件描述符表,文件描述符就是这个表的索引,文件描述符表中每个表项都有一个指向已打开文件的指针。现在我们明确一下:已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体。
file结构体才是内核中用来描述文件属性的结构体。
系统调用详解
系统调用的基本概念:通常,在操作系统中都设置了一组用于实现各种系统功能的子程序,并将它们提供给应用程序调用。
程序接口是 OS 专门为用户程序设置的,也是用户程序取得 OS 服务的唯一途径。程序接口通常是由各种类型的系统调用所组成的,因而,也可以说,系统调用提供了用户程序和操作系统之间的接口,应用程序通过系统调用实现其与 OS 的通信,并可取得它的服务。
操作系统中提供了系统调用,使应用程序可以通过系统调用的方法,间接调用操作系统的相关过程,取得相应的服务。
软件中断实现系统调用:
- 软件中断:它是通过软件指令触发的中断。Linux系统内核响应软件中断,从用户态切换到内核态,执行相应的系统调用。
1.Select
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
select允许应用程序监视一组文件描述符,等待一个或者多个文件描述符成为就绪状态,从而完成I/O操作。
-
fd_set 使用数组实现,数组大小使用 FD_SETSIZE 定义,所以只能监听少于 FD_SETSIZE 数量的描述符。有三种类型的描述符类型:readset、writeset、exceptset,分别对应读、写、异常条件的描述符集合。
-
timeout 为超时参数,调用 select 会一直阻塞直到有描述符的事件到达或者等待的时间超过 timeout。
-
成功调用返回结果大于 0,出错返回结果为 -1,超时返回结果为 0。
2.Poll
int poll(struct pollfd *fds, unsigned int nfds, int timeout);
//当timeout为-1时,poll调用将会永远阻塞,直到某个事件发生;timeout为0时,则立即返回
poll 的功能与 select 类似,也是等待一组描述符中的一个成为就绪状态。
Select与Poll比较:
- select默认监听的文件描述符最大是1024,但可以修改,poll则没有文件描述符的限制。
- poll 提供了更多的事件类型,并且对描述符的重复利用上比 select 高。
3.Epoll
/* 1.epoll采用一组函数来完成任务,而不是一个函数 2.epoll把用户关心的文件描述符上的事件放在内核里的事件表中,从而无须像select和poll每次调用都要重复传入文件描述符集或事件集 */
//创建一个指示epoll内核事件表的文件描述符,该描述符将用作其他epoll系统调用的第一个参数,size不起作用。
int epoll_create(int size);
//该函数用于操作内核事件表监控的文件描述符上的事件:注册、修改、删除
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
//在一段超时时间内等待一组文件描述符上的事件,成功则返回就绪文件描述的个数
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
-
epoll_ctl()用于向内核注册新的描述符或者改变某个文件描述符的状态。已注册的文件描述符在内核中会被维护在一棵红黑树上。
-
epoll比select和poll更灵活,没有文件描述符数量的限制。
-
工作模式:
epoll 的描述符事件有两种触发模式:LT(level trigger)和 ET(edge trigger)。
-
LT模式
当epoll_wait()检测fd上有事件发生并将此事件通知应用程序后,将此事会通知给进程,进程可以不立即处理该事件,当应用程序下一次调用epoll_wait()时,epoll_wait还会再次向应用程序通知此事件,直到此事件被处理。同时支持 Blocking 和 Non-Blocking。
-
ET模式
当epoll_wait()检测fd上有事件发生并将此事件通知应用程序后,应用程序必须立即处理该事件,因为后续epoll_wait()将不会再向应用程序通知该事件。
只支持 No-Blocking,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。
ET模式在很大程度上降低了epoll事件被重复触发的次数,因此ET模式效率比LT模式高。
-
EPOLLONESHOT
为了避免多个多个线程同时操作一个Socket,可以注册EPOLLONESHOT事件。
我们期望的是一个socket连接在任一时刻都只被一个线程处理,通过epoll_ctl对该文件描述符注册epolloneshot事件,一个线程处理socket时,其他线程将无法处理,当该线程处理完后,需要通过epoll_ctl重置epolloneshot事件
-
同于异
- select和poll的文件描述符是在用户态加入文件描述符集合的,每次调用都需要将整个集合拷贝至内核态;而epoll的文件描述符维护在内核态,每次添加文件描述符的时候都需要执行一次系统调用。
- select使用线性表描述文件描述符集合,文件描述符有上限;poll用链表描述,无上限;epoll则用红黑树描述文件描述符集合,且也没有上限。
- select和poll需要通过遍历整个文件描述符集合,判断哪个文件描述符上有事件发生;而epoll会维护一个ready list,会将就绪事件添加至list,每次调用epol_wait的时候,仅观察list是否有数据即可。
应用场景
-
select应用场景
elect 的 timeout 参数精度为微秒,而 poll 和 epoll 为毫秒,因此 select 更加适用于实时性要求比较高的场景,比如核反应堆的控制。
select 可移植性更好,几乎被所有主流平台所支持。
-
poll应用场景
poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select。
-
epoll应用场景
只需要运行在 Linux 平台上,有大量的描述符需要同时轮询,并且这些连接最好是长连接,因为Epoll的文件的描述符都存在内核中,需要通过系统调用epoll_ctr来改变文件描述符状态,频繁操作会降低效率。
需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势。
版权声明
本文为[Augustu_]所创,转载请带上原文链接,感谢
https://blog.csdn.net/guslee/article/details/124337516
边栏推荐
- SystemVerilog(六)-变量
- Nat Commun|在生物科学领域应用深度学习的当前进展和开放挑战
- 2022江西光伏展,中國分布式光伏展會,南昌太陽能利用展
- 122. The best time to buy and sell stocks II - one-time traversal
- 394. String decoding - auxiliary stack
- 470. Rand10() is implemented with rand7()
- 2022 Shanghai safety officer C certificate operation certificate examination question bank and simulation examination
- ROS package NMEA_ navsat_ Driver reads GPS and Beidou Positioning Information Notes
- 209. Minimum length subarray - sliding window
- Cross domain settings of Chrome browser -- including new and old versions
猜你喜欢
102. 二叉树的层序遍历
The ultimate experience, the audio and video technology behind the tiktok
JS get link? The following parameter name or value, according to the URL? Judge the parameters after
Dry goods | how to extract thumbnails quickly?
2022年茶艺师(初级)考试模拟100题及模拟考试
In JS, t, = > Analysis of
Click Cancel to return to the previous page and modify the parameter value of the previous page, let pages = getcurrentpages() let prevpage = pages [pages. Length - 2] / / the data of the previous pag
2021长城杯WP
1217_ Generating target files using scons
Operation of 2022 mobile crane driver national question bank simulation examination platform
随机推荐
Halo open source project learning (II): entity classes and data tables
JS high frequency interview questions
Oil monkey website address
239. Maximum value of sliding window (difficult) - one-way queue, large top heap - byte skipping high frequency problem
92. Reverse linked list II byte skipping high frequency question
关于gcc输出typeid完整名的方法
SQL optimization for advanced learning of MySQL [insert, primary key, sort, group, page, count]
Error in created hook: "referenceerror:" promise "undefined“
Timestamp to formatted date
高德地图搜索、拖拽 查询地址
587. 安装栅栏 / 剑指 Offer II 014. 字符串中的变位词
470. 用 Rand7() 实现 Rand10()
2022 Jiangxi Photovoltaic Exhibition, China distributed Photovoltaic Exhibition, Nanchang solar energy utilization Exhibition
Construction of functions in C language programming
958. 二叉树的完全性检验
SystemVerilog (VI) - variable
C1 notes [task training chapter I]
Kubernetes service discovery monitoring endpoints
Halo 开源项目学习(二):实体类与数据表
Chrome浏览器的跨域设置----包含新老版本两种设置