IO多路复用select、poll、epoll

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、IO多路复用是什么?

        一句话解释:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力。

        IO多路复用解决了什么问题?

        应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,往往不是在一时间内只处理一个事件,需要同时处理键盘鼠标的输入、网络的连接等等...

        而CPU单核在同一时间只能处理一件事情,这怎么办呢,一种解决办法是对CPU进行时分复用----多个事件流将CPU切割成多个时间片,不同事件流的时间片交替进行。其实在用户层看到的好像很多事件在并行执行一样,事实上并不是,只是时间轮询的比较快而已。

       同样, 对于进程/线程,我们也需要同一时间进行多事件处理,那么怎么办呢,聪明的你肯定不知道(毕竟知道了你也就不用过来查了)-------------------IO多路复用。

        
实现原理:用户将想要监视的文件描述符(File Descriptor)添加到select/poll/epoll函数中,由内核监视,函数阻塞。一旦有文件描述符就绪(读就绪或写就绪),或者超时(设置timeout),函数就会返回,然后该进程可以进行相应的读/写操作。

提示:直奔主题,先把select poll epoll的区别拿出来,然后一一分析!!!!

二、select、poll、epoll的区别

       

                                        select   poll  epoll的区别
selectpollepoll
操作方式遍历遍历回调
底层实现数组链表哈希
io效率

每次回调都进行线性遍历,时间复杂度

为O(n)

每次回调都进行线性遍历,时间复杂度

为O(n)

事件通知方式,事件复杂度为O(1)
最大连接数10241024无限制
fd拷贝每次调用select都需要把fd集合从用户态拷贝到内核态每次调用epoll都需要把fd集合从用户态拷贝到内核态调用epoll_ctl时拷贝进内核并保存,之后每次epoll_wait不返回

二、select

        

       int select(int nfds, fd_set *readfds, fd_set *writefds,
                fd_set *exceptfds, struct timeval *timeout);

select的调用会阻塞到有文件描述符可以进行IO操作或被信号打断或者超时才会返回。select将监听的文件描述符分为三组,每一组监听不同的需要进行的IO操作。readfds是需要进行读操作的文件描述符,writefds是需要进行写操作的文件描述符,exceptfds是需要进行异常事件处理的文件描述符。这三个参数可以用NULL来表示对应的事件不需要监听。

当select返回时,每组文件描述符会被select过滤,只留下可以进行对应IO操作的文件描述符。

select可同时监听的文件描述符数量是通过FS_SETSIZE来限制的,在Linux系统中,该值为1024。

三、poll

        int poll(struct pollfd *fds, nfds_t nfds, int timeout);

poll函数说明    功能: 多路IO复用,委托内核同时帮我们监控多个文件描述符

                       头文件: #include 

                         参数: fds:要监视的文件描述符结构体数组的首地址

                                    nfds: 数组中的有效元素个数,注意不是数组总长度

                                    timeout: 阻塞的超时时间  单位  ms (5s ---> 5000 0  --->非阻塞 负数                                                                                                          永久阻塞)

                                   返回值: 0  超时 -1 出错 >0 就绪的文件描述符的个数

和select用三组文件描述符不同的是,poll只有一个pollfd数组,数组中的每个元素都表示一个需要监听IO操作事件的文件描述符。events参数是我们需要关心的事件,revents是所有内核监测到的事件。

四、epoll

        

int epoll_create(int size);
    int epoll_create1(int flags);

    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);
    int epoll_pwait(int epfd, struct epoll_event *events,
                int maxevents, int timeout,
                const sigset_t *sigmask);

 epoll_create&epoll_create1用于创建一个epoll实例。

epoll_ctl用于往epoll实例中增删改要监测的文件描述符。

epoll_wait则用于阻塞的等待可以执行IO操作的文件描述符直到超时。

在需要同时监听的文件描述符数量增加时,select和poll是O(N)的复杂度,epoll是O(1),在N很小的情况下,差距不会特别大,但如果N很大的前提下,一次O(N)的循环可要比O(1)慢很多,所以高性能的网络服务器都会选择epoll进行IO多路复用。

epoll内部用一个文件描述符挂载需要监听的文件描述符,这个epoll的文件描述符可以在多个线程/进程共享,所以epoll的使用场景要比select&poll要多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MrWang.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值