首页 > 技术文章 > 6. IO复用:select 和 poll

sammei 2014-09-07 18:09 原文

select

#include <sys/select.h>
#include <sys/time.h>

int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set exceptset, const struct timeval *timeout);
  • timeout 设置等待就绪IO的超时时间。有三种可能:

    1. NULL 一直等待直到某个IO就绪
    2. 等待固定的时间
    3. 不等待,立即返回,此时timeout里的成员值都为0
  • readset, writeset, exceptset 指定读、写、异常条件的描述符,如果这三个参数都为NULL,则select相当于一个更精确的sleep。三个参数都是描述符集,通常是整数数组,其中每一个bit代表一个描述符。有四个相关宏:

void FD_ZERO(fd_set *fdset);
void FD_SET(int fd, fd_set *fdset);
void FD_CLR(int fd, fd_set *fdset);
int FD_ISSET(int fd, fd_set *fdset);
  • 待测试描述符个数。它的值是待测试的最大描述符加1.

select返回值有三种可能:

  1. 超时返回,返回值为0
  2. IO就绪返回,返回值为描述符集中就绪的总位数。
  3. 出错返回-1

套接字描述符何时就绪?

读就绪:

  1. 有数据可读,套接字接收缓冲区中的数据字节大于等于套接字接收缓冲区低水位标记的当前大小。此时读操作将读到数据,将返回一个大于0的数值。
  2. 连接的读半部关闭。read返回0,表示EOF
  3. 监听套接字且已完成的连接数不为0,此时accept通常不会阻塞
  4. 有一个错误待出理,此时读操作将返回-1,同时errno置为确切的错误条件。

写就绪:

  1. 缓冲区有空间可写。
  2. 连接的写半部关闭。此时写操作将产生SIGPIPE信号
  3. 使用非阻塞式connect的套接字已建立连接,或者connect已经失败告终
  4. 套接字上有错误待处理。写操作将返回-1.

当某个套接字上发生错误时,select将其标记为即可读又可写。

poll

#include <poll.h>

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

推荐阅读