网站首页 > 技术文章 正文
我们都知道linux的哲学是一切接文件,也就是说无论是我们的进程,线程,还是我们的设备,最后都对应的是文件,而文件操作就是linux的核心。那么linux中有几种操作输入输出的模型呢?答案是三种,就是select,poll,epoll。
select
这个模型是在1983年的unix系统中引入的,它通过fd_set变量来控制设备需要等待什么。也就是说linux中有个select函数,我们是通过它来监控文件状态的。
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeval *timeout);
(1)intmaxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错。
说明:对于这个原理的解释可以看上边fd_set的详细解释,fd_set是以位图的形式来存储这些文件描述符。maxfdp也就是定义了位图中有效的位的个数。
(2)fd_set*readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读;如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。
(3)fd_set*writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。
(4)fd_set*errorfds同上面两个参数的意图,用来监视文件错误异常文件。
(5)structtimeval* timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第三,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即 select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。
poll
poll在1986年引入unix中,在linux中是在1997年引入的。它的函数定义为:
int poll ( struct pollfd * fds, unsigned int nfds, int timeout);
fds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符;每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select()函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况;
epoll
epoll是在linux2.5内核中引入的,目前是比poll和select模型都要高效。epoll实现主要实现三个接口。
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_create建立一个epoll对象。参数size是内核保证能够正确处理的最大句柄数。
然后,epoll_ctl可以操作上面建立的epoll,例如,将刚建立的socket加入到epoll中让其监控,或者把 epoll正在监控的某个socket句并移出epoll,不再监控它等等。
最后,epoll_wait在调用时,在给定的timeout时间内,当在监控的所有句柄中有事件发生时,就返回用户态的进程。
epoll提供两种触发模式,一种水平触发,一种边缘触发。
水平触发:就是只有高电平(1)或低电平(0)时才触发通知,只要在这两种状态就能得到通知。
边缘触发:只有电平发生变化(高电平到低电平,或者低电平到高电平)的时候才触发通知。
简单理解,在水平触发的时候,可以时刻监测IO的状态,而边缘触发,只有下次IO活动到来的时候,才进行通知。因此,当监视数量描述符多的时候,边缘触发的epoll效率更高。
# operations | poll | select | epoll
10 | 0.61 | 0.73 | 0.41
100 | 2.9 | 3.0 | 0.42
1000 | 35 | 35 | 0.53
10000 | 990 | 930 | 0.66
总结
epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。
猜你喜欢
- 2024-11-03 linux 内核poll/select/epoll实现剖析(经典)-下
- 2024-11-03 Linux I/O复用中select poll epoll模型的介绍及其优缺点的比较
- 2024-11-03 IO多路复用之select、poll、epoll之间的区别总结
- 2024-11-03 网络编程——C++实现socket通信(TCP)高并发之select模式
- 2024-11-03 Java面试八股文Netty网络编程,select
- 2024-11-03 「Linux网络编程」TCP并发服务器的实现(IO多路复用select)
- 2024-11-03 linux 内核poll/select/epoll实现剖析(经典)-上
- 2024-11-03 I/O复用 - select&poll(i/o复用不会阻塞用户进程)
- 2024-11-03 深入学习IO多路复用 select/poll/epoll 实现原理
- 2024-11-03 linux并发服务器模型三、Select(linux高并发服务器)
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)