Linux I/O多路复用机制

I/O多路复用是为了解决进程或线程阻塞到某个I/O系统调用而出现的技术,使进程或线程不阻塞某个特定的I/O系统调用;

I/O多路复用机制包括select、poll、epoll;I/O复用可以监视多个描述符,一旦某个描述符就绪,能够通知程序进行相应的操作;

select()

 

它的头文件和函数原型如下:

#include<sys/select.h>
int select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval *timeout)

select()函数监视的文件描述符分3类,分别是writefds、readfds、exceptfds;调用select()函数会阻塞,直到有描述符就绪或者超时才返回,当函数返回后,可以通过遍历fdset来找到就绪的文件描述符

参数含义:

nfds:要监视的文件描述符的范围,Linux上最大值一般为1024

readfds:监视的可读描述符集合

writefds:监视的可写 描述符集合

exceptfds:监视的错误异常描述符集合

timeout:超时时间,它告知内核等待所指定描述字中的任何一个就绪可花多少时间;timeval结构用于指定这段时间的秒数和微秒数

poll()

 

select()和poll()系统调用的本质一样,与select()在本质上没有多少差别,管理多个描述符也是进行轮询的,但是poll()没有最大文件描述符数量的限制;它和select()存在同一个缺点,包含大量文件描述符的数组被整体复制与用户态和内核态的地址空间,它的开销随文件描述符数量的增加而线性增大

所需头文件和函数原型如下:

#include<poll.h>
int poll(struct pollfd * fds,nfds_t nfds,int timeout);

参数含义:

fds:与select()使用的fd_set的方式不同,poll()使用一个pollfd的指针实现;一个pollfd结构体包括监视的文件描述符和事件

struct pollfd
{
    int fd;       //文件描述符
    short events; //等待的事件
    short revents;//实际发生的事件
}

nfds:用来指定第一个参数数组元素个数

timeout:指定等待的毫秒数 

epoll()

 

相对于select()和poll(),epoll更加灵活,没有描述符限制,epoll使用一个文件描述符管理多个描述符,将用户关心的文件描述符的事件存放在内核的一个时间表中,这样在用户空间和内核空间只需要一次

//epoll操作的三个接口
#include<sys/epoll.h>
//该函数生成一个epoll专用的文件描述符
int epoll_create(int size) //size用来告诉内核监听的数目一共多大,从Linux 2.6.8之后就被忽略
//epoll的事件注册函数,注册要监听的事件类型
int epoll_ctl(int epfd,int op,int fd,struct epoll_event * event);
//epfd:epoll专用的文件描述符,create的返回值
//op:表示动作;ADD注册新的fd到epfd中; MOD修改已注册的监听事件; DEL删除一个fd;
//struct epoll_event结构如下:
typedef union epoll_data
{
    void * ptr;
    int fd;
    __uint32_t u32;
    __uint64_t u64;
}epoll_data_t  //保存触发事件的某个文件描述符的相关数据

//感兴趣的事件和触发事件

struct epoll_event
{
    __uint32_t events;
    epoll_data_t data;
}

//等待事件的产生,收集epoll监控的事件中已经发生的事件

int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);
//events不可以是空指针,内核只负责把数据复制到这个events数组中,不会去帮助我们在用户态中分配内存
//maxevents:内核中有多少个events

epoll对文件描述符的操作有两种模式:

LT(level trigger)模式:该模式是默认模式,支持block和no_block socket;当epoll_wait检测到描述符事件发生并将该事件通知应用程序,应用程序不立即处理该事件,下次调用epoll_wait时,会再次响应应用程序并通知此事件,在高并发、大流量情况下,效率低于ET模式;只要有数据没有被获取,内核就不断通知,不用担心事件丢失情况

ET(edge trigger)模式高效模式;只支持no_block socket,当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立刻处理,如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件; 在高并发、大流量情况下,效率非常高,需要细致的处理每个请求,否则容易丢失事件

select()、poll()、epoll()应用场景对比:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值