IO多路复用及select,poll,epoll详解

一 什么是IO多路复用,为什么要IO多路复用。

在不使用线程,独立处理文件的情况下,进程无法在多个文件描述符上阻塞。

同步阻塞IO:假如其中某个文件描述符没有准备好,进程就会阻塞,不能再处理其它文件,直到该文件描述符准备好。

同步非阻塞IO:假如其中某个文件描述符没有准备好,向进程返回一个错误信息,从而避免阻塞。

若是采用非阻塞IO,进程需要以某种不确定的方式不断发起IO操作,直到某个打开的文件描述符已经就绪。

IO多路复用允许应用在多个文件描述符上同时阻塞,直到有一个或者更多的文件描述符处于就绪状态,然后处理已经就绪的文件描述符。Linux提供了三种IO多路复用方案:select ,poll,epoll。

二 多路复用的三种实现

(1)select

select函数原型:

int select(int n,fd_set* readfds,fd_set* writefds,fd_set* exceptions,struct timeval* timeout);

n:所有集合中文件描述符的最大值加1.

writefds:监测writefds集合中,是否至少有一个写操作可以不阻塞的完成。

readfds:监测readfds集合中,是否至少有一个读操作可以不阻塞的完成。

exceptions:监测exceptions集合中是否有出现异常发生。

timeout:这是一个结构体,设定时间限制,超过该时间,select函数会返回。

成功返回时,每个集合中只包含对应类型的IO就绪的文件描述符,同时返回在三个集合中IO就绪的数目。

在每次使用调用select时,需要使用辅助宏FD_ZERO将制定集合中所有文件描述符移除。同时,可以利用

FD_SET向某个集合中添加文件描述符。

(2)poll

poll函数原型:

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

fds:结构体数组指针,指定要监听的文件描述符集合。

struct pollfd//指定监听的单一文件描述符

{

int fd;//文件描述符

short events;//监听的集合,要监视的文件描述符事件的一组位掩码。

short revents;//返回的集合,发生在该文件描述符上的时间的位掩码。

}

nfds:需要监听的文件描述符的个数。

timeout:在任何IO就绪前等待的时间长度,超过该值,poll调用阻塞。

成功时,函数返回具有非零revents字段的文件描述符的个数。

(3) epoll

提供三个函数接口:

 int epoll_create(int size)
创建一个epoll的句柄,size表示监听数目。创建完句柄后,会占用一个fd。在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);//epoll的事件注册函数。

epfd:返回值

op:动作,可以取值EPOLL_CTL_ADD(注册新的fd);EPOLL_CTL_MODE(修改已经注册的fd监听时间);POLL_CTL_DEL(删除fd)。

fd:需要监听的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 events */
    epoll_data_t data; /* User data variable */
};

3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

epfd:返回值。

events:从内核得到的事件的集合。

maxevents:events事件数目,不能超过size。

timeout:超时时间。超时,epoll会阻塞。

三 select\poll\epoll的比较

select与poll比较:

(1)select需要就算最大文件描述符值加1,并传递该参数,poll不需要。

(2)poll在文件描述符值较大时,效率更高。select需要从头到尾进行遍历.

(3)文件描述符集合在返回时会被重建。poll中输入数组不需要改变。

(4)select可移植性更好,某些unix系统不支持poll。

(5)select 上限为1024,poll要大很多。

 (6)每次调用select或者poll时,都要将文件描述符拷贝到内核空间,然后都是从头到尾遍历。两个开销都很大。

epoll性能比select和poll都要好:

(1)在epoll_ctl中,每次注册新的文件描述符到epoll句柄中时,会把所有的文件描述符拷贝进内核(文件描述符存在红黑树中,不会被重复加入),而不是在epoll_wait时候重复拷贝。epoll保证了每个文件描述符只被拷贝一次。

(2)内核通过为每一个文件描述符指定一个回调函数,当文件描述符就绪时,回调函数将文件描述符加入一个就绪链表,epoll_wait查看这个就绪链表是否有就绪文件描述符。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值