fbpx
维基百科

select (Unix)

select是用于I/O多路转接的一个系统调用函数。

C程序中,该系统调用在 sys/select.h 或 unistd.h 中声明,语法如下:

int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, struct timeval* timeout); 
参数 描述
nfds sets的文件描述符的最大值
readfds fd_set 类型,包含了需要检查是否可读的描述符,输出时表示哪些描述符可读。可为 NULL
writefds fd_set 类型,包含了需要检查是否可写的描述符,输出时表示哪些描述符可写。可为 NULL
errorfds fd_set 类型,包含了需要检查是否出错的描述符,输出时表示哪些描述符出错。可为 NULL
timeout struct timeval 类型的结构体,表示等待检查完成的最长时间。

为了维护fd_set类型的参数,会使用下面四个:FD_SET(), FD_CLR(), FD_ZERO() 和 FD_ISSET()。

返回值

 这个函数将返回描述符集的个数, 如果超时返回为0,错误则返回-1。 

参看

  • select(2)
  • poll(2)

select与epoll的区别 编辑

epoll select
概述 epoll是个模块,由三个系统调用组成,内核中由用文件系统实现 select是个系统调用
结构体定义
typedef union epoll_data {  void *ptr;  int fd;  __uint32_t u32;  __uint64_t u64; } epoll_data_t; struct epoll_event {   __uint32_t events; // epoll 监听的事件类型  epoll_data_t data; /* User data variable */ }; 
struct timeval{  long tv_sec;//second  long tv_usec;//minisecond } typedef struct fd_set {  u_int fd_count;  int fd_array[FD_SETSIZE]; } //fd_array可SIZE*8个socket 
可用的事件

EPOLLIN :表示对应的文件描述符可以读;
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI: 表示对应的文件描述符有紧急的数据可读;
EPOLLERR: 表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: ET的epoll工作模式;

fd_set有三种类型:

readfds, writefds, exceptionfds


操作函数 三个系统调用:epoll_create epoll_ctl epoll_wait 一个系统调用:select
四个宏: FD_ZERO FD_SET FD_CLR FD_ISSET
运行模式 边沿触发 (ET)、状态触发 (LT)  状态触发
运行过程  
int fd = epoll_create(1); // 创建一个 epoll 实例,参数可以是任意正整数 struct epoll_event events[xxxB];// epoll 实例将发生的事件写入该数组 while(1){  int nfds = epoll_wait( ); // 等待事件发生  for(int i=0; i<nfds; i++){    }//end for }//end while 
struct timeval tv; fd_set rfds; tv={5,0}; // 设置超时 while(1){  FD_ZERO(&rfds);  if (!select()) continue;  for(int i=0;i<maxfds; i++){  ...  } // 结束 for 循环 } // 结束 while 循环 
优点 1)epoll_wait返回的都是有效数据,可直接从struct epoll_event[]中获取事件,效率高。
缺点 每次select有数据要遍历全部socket
注意事项 每次取事件后,要重新注册此socket的事件epoll。(epoll_ctl) 每次select之前要重置rfds的值。(FD_ZERO)

说明:以上无论epoll_create, fd_set都受限于系统中单个进程能够打开的文件句柄数。

示例 编辑

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <sys/select.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #define PORT "9421" /* function prototypes */ void die(const char*); int main(int argc, char **argv) {  int sockfd, new, maxfd, on = 1, nready, i;  struct addrinfo *res0, *res, hints;  char buffer[BUFSIZ];  fd_set master, readfds;  ssize_t nbytes;  (void)memset(&hints, '\0', sizeof(struct addrinfo));  hints.ai_family = AF_INET;  hints.ai_socktype = SOCK_STREAM;  hints.ai_protocol = IPPROTO_TCP;  hints.ai_flags = AI_PASSIVE;  if(-1 == (getaddrinfo(NULL, PORT, &hints, &res0)))  die("getaddrinfo()");  for(res = res0; res; res = res->ai_next)  {  if(-1 == (sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)))  {  perror("socket()");  continue;  }  if(-1 == (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(int))))  {  perror("setsockopt()");  continue;  }  if(-1 == (bind(sockfd, res->ai_addr, res->ai_addrlen)))  {  perror("bind");  continue;  }  break;  }  if(-1 == sockfd)  exit(EXIT_FAILURE);  freeaddrinfo(res0);  if(-1 == (listen(sockfd, 32)))  die("listen()");  if(-1 == (fcntl(sockfd, F_SETFD, O_NONBLOCK)))  die("fcntl()");  FD_ZERO(&master);  FD_ZERO(&readfds);    FD_SET(sockfd, &master);  maxfd = sockfd;  while(1)  {  memcpy(&readfds, &master, sizeof(master));  (void)printf("running select()\n");  if(-1 == (nready = select(maxfd+1, &readfds, NULL, NULL, NULL)))  die("select()");  (void)printf("Number of ready descriptor: %d\n", nready);  for(i=0; i<=maxfd && nready>0; i++)  {  if(FD_ISSET(i, &readfds))  {  nready--;  if(i == sockfd)  {  (void)printf("Trying to accept() new connection(s)\n");  if(-1 == (new = accept(sockfd, NULL, NULL)))  {  if(EWOULDBLOCK != errno)  die("accept()");  break;  }    else  {  if(-1 == (fcntl(new, F_SETFD, O_NONBLOCK)))  die("fcntl()");  FD_SET(new, &master);  if(maxfd < new)  maxfd = new;  }  }  else  {  (void)printf("recv() data from one of descriptors(s)\n");  nbytes = recv(i, buffer, sizeof(buffer), 0);  if(nbytes <= 0)  {  if(EWOULDBLOCK != errno)  die("recv()");  break;  }  buffer[nbytes] = '\0';  printf("%s", buffer);    (void)printf("%zi bytes received.\n", nbytes);  close(i);  FD_CLR(i, &master);  }  }  }  }  return 0; } void die(const char *msg) {  perror(msg);  exit(EXIT_FAILURE); } 

参见 编辑

外部链接 编辑

select, unix, 此條目包含過多行話或專業術語, 可能需要簡化或提出進一步解釋, 2012年11月29日, 請在討論頁中發表對於本議題的看法, 並移除或解釋本條目中的行話, 此條目没有列出任何参考或来源, 2010年5月5日, 維基百科所有的內容都應該可供查證, 请协助補充可靠来源以改善这篇条目, 无法查证的內容可能會因為異議提出而被移除, select是用于i, o多路转接的一个系统调用函数, 在c程序中, 该系统调用在, select, unistd, 中声明, 语法如下, select, nfds,. 此條目包含過多行話或專業術語 可能需要簡化或提出進一步解釋 2012年11月29日 請在討論頁中發表對於本議題的看法 並移除或解釋本條目中的行話 此條目没有列出任何参考或来源 2010年5月5日 維基百科所有的內容都應該可供查證 请协助補充可靠来源以改善这篇条目 无法查证的內容可能會因為異議提出而被移除 select是用于I O多路转接的一个系统调用函数 在C程序中 该系统调用在 sys select h 或 unistd h 中声明 语法如下 int select int nfds fd set readfds fd set writefds fd set errorfds struct timeval timeout 参数 描述nfds sets的文件描述符的最大值readfds fd set 类型 包含了需要检查是否可读的描述符 输出时表示哪些描述符可读 可为 NULL writefds fd set 类型 包含了需要检查是否可写的描述符 输出时表示哪些描述符可写 可为 NULL errorfds fd set 类型 包含了需要检查是否出错的描述符 输出时表示哪些描述符出错 可为 NULL timeout struct timeval 类型的结构体 表示等待检查完成的最长时间 为了维护fd set类型的参数 会使用下面四个宏 FD SET FD CLR FD ZERO 和 FD ISSET 返回值 这个函数将返回描述符集的个数 如果超时返回为0 错误则返回 1 参看 select 2 poll 2 目录 1 select与epoll的区别 2 示例 3 参见 4 外部链接select与epoll的区别 编辑epoll select概述 epoll是个模块 由三个系统调用组成 内核中由用文件系统实现 select是个系统调用结构体定义 typedef union epoll data void ptr int fd uint32 t u32 uint64 t u64 epoll data t struct epoll event uint32 t events epoll 监听的事件类型 epoll data t data User data variable struct timeval long tv sec second long tv usec minisecond typedef struct fd set u int fd count int fd array FD SETSIZE fd array可SIZE 8个socket可用的事件 EPOLLIN 表示对应的文件描述符可以读 EPOLLOUT 表示对应的文件描述符可以写 EPOLLPRI 表示对应的文件描述符有紧急的数据可读 EPOLLERR 表示对应的文件描述符发生错误 EPOLLHUP 表示对应的文件描述符被挂断 EPOLLET ET的epoll工作模式 fd set有三种类型 readfds writefds exceptionfds操作函数 三个系统调用 epoll create epoll ctl epoll wait 一个系统调用 select 四个宏 FD ZERO FD SET FD CLR FD ISSET运行模式 边沿触发 ET 状态触发 LT 状态触发运行过程 int fd epoll create 1 创建一个 epoll 实例 参数可以是任意正整数 struct epoll event events xxxB epoll 实例将发生的事件写入该数组 while 1 int nfds epoll wait 等待事件发生 for int i 0 i lt nfds i end for end while struct timeval tv fd set rfds tv 5 0 设置超时 while 1 FD ZERO amp rfds if select continue for int i 0 i lt maxfds i 结束 for 循环 结束 while 循环优点 1 epoll wait返回的都是有效数据 可直接从struct epoll event 中获取事件 效率高 缺点 每次select有数据要遍历全部socket注意事项 每次取事件后 要重新注册此socket的事件epoll epoll ctl 每次select之前要重置rfds的值 FD ZERO 说明 以上无论epoll create fd set都受限于系统中单个进程能够打开的文件句柄数 示例 编辑 include lt stdio h gt include lt stdlib h gt include lt string h gt include lt sys types h gt include lt sys socket h gt include lt netinet in h gt include lt netdb h gt include lt sys select h gt include lt fcntl h gt include lt unistd h gt include lt errno h gt define PORT 9421 function prototypes void die const char int main int argc char argv int sockfd new maxfd on 1 nready i struct addrinfo res0 res hints char buffer BUFSIZ fd set master readfds ssize t nbytes void memset amp hints 0 sizeof struct addrinfo hints ai family AF INET hints ai socktype SOCK STREAM hints ai protocol IPPROTO TCP hints ai flags AI PASSIVE if 1 getaddrinfo NULL PORT amp hints amp res0 die getaddrinfo for res res0 res res res gt ai next if 1 sockfd socket res gt ai family res gt ai socktype res gt ai protocol perror socket continue if 1 setsockopt sockfd SOL SOCKET SO REUSEADDR char amp on sizeof int perror setsockopt continue if 1 bind sockfd res gt ai addr res gt ai addrlen perror bind continue break if 1 sockfd exit EXIT FAILURE freeaddrinfo res0 if 1 listen sockfd 32 die listen if 1 fcntl sockfd F SETFD O NONBLOCK die fcntl FD ZERO amp master FD ZERO amp readfds FD SET sockfd amp master maxfd sockfd while 1 memcpy amp readfds amp master sizeof master void printf running select n if 1 nready select maxfd 1 amp readfds NULL NULL NULL die select void printf Number of ready descriptor d n nready for i 0 i lt maxfd amp amp nready gt 0 i if FD ISSET i amp readfds nready if i sockfd void printf Trying to accept new connection s n if 1 new accept sockfd NULL NULL if EWOULDBLOCK errno die accept break else if 1 fcntl new F SETFD O NONBLOCK die fcntl FD SET new amp master if maxfd lt new maxfd new else void printf recv data from one of descriptors s n nbytes recv i buffer sizeof buffer 0 if nbytes lt 0 if EWOULDBLOCK errno die recv break buffer nbytes 0 printf s buffer void printf zi bytes received n nbytes close i FD CLR i amp master return 0 void die const char msg perror msg exit EXIT FAILURE 参见 编辑Berkeley套接字 轮询 epoll kqueue IOCP外部链接 编辑select 2 Linux程序员手册页 系统调用 System Calls select tut 2 Linux系统调用 System Calls 手册页 取自 https zh wikipedia org w index php title Select Unix amp oldid 60464339, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。