详解select,poll和epoll函数

select:

select的原型如下:

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

n是需要监视的最大的文件描述符+1

select监视的fd分为三类,分别是readfds,writefds和exceptfds。调用select之后会阻塞,直到有描述符就绪,或者超时(timeout指定等待时间,如果设为null则立即返回),函数返回。

fd_set是一组fd的集合,它用一位来表示一个fd

可以使用宏操作fd_set:

fd_set set;
FD_ZERO(&set);  //clear all bits in set
FD_SET(3, &set);  //turn on bit 3 in set
FD_CLR(2, &set);  //clear bit 2 in set
FD_ISSET(5, &set); //is bit 5 in set on?

select返回之后,通过遍历fdset,来找到就绪的描述符。

一个摘自csapp中的例子(只列出了关键代码):

// read_set is original set, ready_set is working set
fd_set read_set, ready_set;

listenfd = Open_listenfd(port); // call socket, bind...返回监听描述符

FD_ZERO(&read_set);
FD_SET(STDIN_FILENO, &read_set)
FD_SET(listenfd, &read_set)

while(1){
  ready_set = read_set;   // suppose now ready_set : 0001 0001, bit 0 is STDIN_FILENO, bit 4 is listenfd
  select(listenfd+1, &ready_set, NULL, NULL, NULL);  
  if (FD_ISSET(STDIN_FILENO, &ready_set))  // if only STDIN_FILENO is active, now ready_set: 0000 0001
    command();
  if (FD_ISSET(listenfd, &ready_set))  //if only listenfd is active, now ready_set: 0001 0000
    connfd = accept(listenfd, (SA *)&clientaddr, &clientlen);
    echo(connfd);
    close(connfd);  
 }

//这里省略了command(), echo()函数的实现

 select几乎在所有的平台上都支持,跨平台好。缺点主要是单个进程能监视的fd有限制,一般为1024.可通过其他方式调整。

原文地址:https://www.cnblogs.com/geeklove01/p/8998611.html