troubleasy

导航

 

select,poll,epoll是io多路复用技术;(阻塞+不考虑线程,进程)

应用场景:标准输入,套接字等都可以看做I/O的一路,当任何一路上的io事件发生时,内核移交控制权给应用程序进行io事件处理;

io事件诸如:标准输入文件描述符准备好可以读;监听套接字准备好,新的连接已经建立成功;已连接套接字准备好可以写;如果io事件等待超过10秒,发生了超时事件。

select:

维护三个描述符集合:读描述符集合,写描述符结合,异常描述符集合。

循环过程中初始化待测试的描述符集合,调用select,当待测试的描述符上有io事件发生时,解除阻塞,调用应用程序处理io事件。

缺点:支持的描述符个数有限。

poll:

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

若有就绪描述符则返回其数目,超时返回0,出错返回-1

struct pollfd{

  int fd;//文件描述符

  short events;//事件性质,POLLIN表示读事件,POLLOUT表示写事件

  short revents;//poll检测后的返回值

};

timout为-1,调用者进程被阻塞,直到内核io事件的分发。fds为带有事件属性的描述符集合,将监听套接字加入fds,表示期望内核检测监听套接字的连接建立完成事件。当有io事件触发时,遍历所有的文件描述符。

epoll:

随着文件描述符增多,epoll的性能远远高于select,poll。添加两个机制:边缘触发和水平触发。epoll较poll性能提升的一点在于epoll只遍历触发io事件的就绪文件描述符。

int epoll_create(int size)//创建epoll实例;

int epoll_ctl(int epfd,int op,int fd,struct epoll_event*event);//向epoll实例里添加 或删除监控文件描述符。

epfd :epoll实例描述符;

op:标识删除还是增加事件;

fd:文件描述符;

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;

};

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

//类似select或者poll用于内核io事件分发,若无io事件,则调用者阻塞。返回值为io事件个数,无io事件返回0;

epfd:epoll实例描述符;

events待调用的事件集合;

tiimeout设置为-1,表示不超时,设置为0,表示没有io事件发生,立即返回。

创建epoll实例后,将监听套接字对应的io事件加入到epoll,这样有新的连接的时候,会被感知到;当监听套接字被触发时,再把新的socket注册到epoll中;

边缘触发和条件触发的适用情况:

条件触发(LT):只要满足条件,比如有数据可读,就一直不断地把这个事件传递给用户,比如listen_fd加入epoll时候,标识为LT;大块数据远远大于缓存时。

边缘触发(ET):只有第一次满足条件的时候才触发。

 

posted on 2020-06-17 00:33  troubleasy  阅读(1637)  评论(0编辑  收藏  举报