1、多路复用机制Select、poll、epoll
IO多路复用就是通过一种机制,一个进程就可以监视多个描述符,一旦某个描述符就位(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作
select、poll、epoll是Linux API提供的IO复用方式
2、API原型
select
select系统调用是用来让我们的程序监视多个文件句柄的状态变化的
select函数监视的文件描述符分3类:
writefds、readfds、exceptfds
调用后select函数会阻塞,直到有描述符就绪(有数据可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。
select的缺点:
1、单个进程可监视的fd数量被限制,即能监听端口的大小有限
2、对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低
3、需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该机构时复制开销大
poll
和select函数一样,监听多个文件描述符,知道条件满足或超过的时候poll返回,通过遍历文件描述符来获取已经就绪的描述符。
不同于select使用三个位图来表示三个fdset的方式,poll使用一个pollfd的指针实现
pollfd并没有最大数量限制(但是数量过大后性能也是会下降)
poll的缺点:
缺点基本与select函数一致
1.poll返回后,通过遍历文件描述符来获取已经就绪的描述符。
2.同时连接的大量客户端在一-时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。
epoll
epoll是在2.6内核中提出的,是select和poll的增强版本
epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。
epoll的优点:
1、监视的描述符数量不受限制
它所支持的FD_上限是最大可以打开文件的数目, 这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat/proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。
2、IO的效率不会随着监视fd的数量的增长而下降
epoll不同于select和poll轮询的方式,而是通过每个fd定义的回调函数来实现的。只有就绪的fd才会执行回调函数。
3. epoll使用一个文件描述符管理多个描述符
将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。
3、性能对比
4、poll方法实现
unsigned int (*poll) (struct file *, struct poll_ table_ struct *)
返回值: event事件
static inline
void poll_wait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
typedef struct poll_table_struct {
poll_queue_proc _qproc;
unsigned long _key;
} poll_table;
事件类型:
5、参考实例
static unsigned int hello_ poll (struct file * filep, struct poll_ table_ struct *ptable)
{
unsigned int mask = 0;
poll _wait(filep,&rq,ptable);
poll _wait(filep,&wq,ptable);
if(have_ data == 1)
{
mask | = POLLIN;
if(have_ data == 0)
{
mask| = POLLOUT;
}
return mask;
}