转载

select、poll、 epoll详解

select、poll、 epoll详解

IO模型:通用的IO模型,包括阻塞式IO模型、非阻塞式模型、IO复用模型和信号驱动模型。

IO复用:一个线程监控多个IO流,一旦一个或多个IO条件就绪,就直接返回。

select、poll和epoll是实现IO复用的函数。

select

//select函数
int select(int maxfdpl, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout)
//返回:若有就绪描述符则为其数目,若超时则为零,若出错则为-1 
 
struct timeval{
	long tv_sec; /*second*/
    long tv_usec; /*microseconds*/
}
  • timeout参数

    其结构如上代码所示,总共分为三种情况

    1、timeout为空,一直等待,直到有IO条件就绪,才返回。

    2、timeout结构体,两个变量有不为零,等待指定时间,监控IO流,一旦超时立即返回0

    3、timeout结构体,两个变量均为零,直接不等待,轮询一遍,立即返回

  • readset、writeset、exceptset参数

    以上三个参数是指定内核测试读、写和异常条件的文件描述符集

    文件描述符集,通常是一个整数数组,其中每个整数中的每一位对应一个描述符。举例来说

    假设使用32位整数,那么该数组的第一个元素对应于描述符0~31,第二个元素对应于描述符32

    -63,以此类推。举个例子,以下代码,定义一个fd_set类型变量,然后打开描述符1,4和5对应位,(意思就是监控描述符1,4,5,具体是监控读、写还是异常,看赋给那个参数)

    fd_set rset;
    FD_ZERO(&rset); //初始化为全零
    FD_SET(1, &rset);
    FD_SET(4, &rset);
    FD_SET(5, &rset);
    
  • maxfdpl

    指定待测试的描述符个数,值是待测试最大描述符加一,即描述符0,1,2.。直到maxfdpl-1将被测试

  • 结果返回

    select函数会修改readset、writeset、exceptset三个参数,就绪的描述符将置为1,未就绪的

    描述符将重置为零。之后函数的返回结果为就绪描述符的数目。

poll

#include<poll.h>
int poll(struct pollfd *fdarray, unsigned long nfds, int timeout)
//返回:若有就绪描述符则为其数目,若超时则为0,若出错则为-1
  • fdarray

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

    fdarray指向结构体数组的第一个元素指针,每个元素都是pollfd结构体。要测试的条件由

    events指定,函数在相应的revents返回该文件描述符的状态

  • nfds参数,指定结构数组的元素个数

  • timeout参数,指定poll返回前等待多长时间。作用类似select函数的timeout结构体

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);
              
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 */
};

epoll接口,主要分为三个阶段

1、epoll_create函数创建epoll文件描述符

2、epoll_ctl对指定的文件描述符fd的监听事件event进行操作,主要有添加、删除和修改三种动作

3、epoll事先通过epoll_ctl()来注册多个文件描述符事件,一旦基于某个文件描述符事件就绪时,内核会采用类似callback的回调机制,通知正在调用epoll_wait函数的进程。

epoll优点

  • 监控描述符不受限制

  • IO效率不会随着监控fd的数量的增长而下降

  • 支持电平触发和边沿触发。

    只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发两种方式,理论上边缘触发的性能要更高一些,但是代码实现相当复杂。

  • mmap加速内核与用户空间的信息传递。epoll是通过内核与用户空间同一块内存,避免了无畏的内存copy.

参考资料

linux中select poll epoll的区别比较

UNIX网路编程

正文到此结束
本文目录