目录

一、概念

二、流程

三、select、poll、epoll介绍

1.select

2.poll

3.epoll


一、概念

I/O复用模型:主要是指,一个线程可以同时监控多个系统IO、并且能够操作多个系统IO的一种技术模型;目前主要有:select、poll、epoll等技术模型。

二、流程

ios 复用Views io复用模型_文件描述符

说明: select/poll/epoll核心是可以通过一个线程同时处理多个socket链接,并不会使得每次操作io的过程变快。因此,IO复用模型的设计并不是位了快,而是为了解决线程、进程数量过多(数量过多会导致系统频繁切换cpu资源,造成操作系统压力)对服务器开销造成的压力。

三、select、poll、epoll介绍

IO复用模型是通过一种机制,一个线程可以同时监控多个socket,其中某些socket就绪(读、写事件就绪)后能快速通知程序进程对应的IO操作。IO复用模型一般为异步阻塞IO,但select、poll、epoll本质上还是同步IO(都是需要读写事件就绪后再进行读写,而且整个读写的过程是阻塞的),真正意义上的异步IO是不需要负责进行读写操作的。

1.select

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

select函数监视的文件描述符有三类,readfds,writefds,exceptfds。调用后函数会阻塞,直到有描述符就绪(有数据读、写、或者有except),或者超时(timeout指定时间,如果立即返回设置null),函数返回。当select函数返回后,可以通过便利fdset,来找到就绪的描述符。

优点:良好的跨平台性。

缺点:单个进程能够监视的文件描述符的数量存在最大限制,在Linux上为1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但这样会造成效率的降低。

2.poll

int poll(struct poll *fds, unsigned int nfds, int timeout);
struct pollfd{
  int fd;
  short events;
  short revents;
};

与select使用三个位图来表示fdset,poll使用一个pollfd的指针实现。pollfd结构包含了要监视的event和发生的event,不在使用select参数传值的方式。同时pollfd并没有最大数量的限制(但数量过大性能也会下降)。和select一样,poll返回后,需要轮询pollfd来或许就绪的描述符。

3.epoll

//生成一个epoll专用的文件描述符
//参数:size就是你在这个epoll fd上能关注的最大socket fd数
//返回值:成功 fd,失败0
int epoll_create(int size)

//该函数用于控制某个epoll文件描述符上的事件,可以注册事件,修改事件,删除事件。
//参数:
//epfd:由 epoll_create 生成的epoll专用的文件描述符;
//op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除
//fd:关联的文件描述符;
//event:指向epoll_event的指针;
//返回值:如果调用成功返回0,不成功返回-1
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

//该函数用于轮询I/O事件的发生;
//参数:
//epfd:由epoll_create 生成的epoll专用的文件描述符;
//epoll_event:用于回传代处理事件的数组;
//maxevents:每次能处理的事件数;
//timeout:等待I/O事件发生的超时值(单位我也不太清楚);-1相当于阻塞,0相当于非阻塞。一般用-1即可
//返回值:发生事件数。
int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)

epoll是select和poll的增强版本,相比于前两者,它更加的灵活,没有描述符的限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需要一次。