Linux select分析

select的作用

初学socket时,习惯使用connent、accept、recv或者recvfrom来阻塞程序。然而使用select可以完成非阻塞方式,监视需要被监视的文件描述符的变化情况——读写或异常。

相关数据结构

fd_set,实际是一个long int 类型的数组,其中的每一个 bit 代表一个文件描述符,一般最多表示1024个文件描述符 (sys/select.h) 

 1 /* fd_set for select and pselect. */
 2 typedef struct
 3   {
 4     /* XPG4.2 requires this member name. Otherwise avoid the name
 5        from the global namespace. */
 6 #ifdef __USE_XOPEN
 7     __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
 8 # define __FDS_BITS(set) ((set)->fds_bits)
 9 #else
10     __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
11 # define __FDS_BITS(set) ((set)->__fds_bits)
12 #endif
13   } fd_set;
View Code

关于fd_set的一些操作:(宏定义)

FD_CLR(fd, &fdset)  
// Clears the bit for the file descriptor fd in the file descriptor set fdset.

FD_ISSET(fd, &fdset)  
// Returns a non-zero value if the bit for the file descriptor fd is set in the file descriptor set pointed to by fdset, and 0 otherwise.

FD_SET(fd, &fdset)  
// Sets the bit for the file descriptor fd in the file descriptor set fdset.

FD_ZERO(&fdset)  
// Initializes the file descriptor set fdset to have zero bits for all file descriptors.
View Code

函数

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
/*
int maxfdp:集合中所有文件描述符的范围,为所有文件描述符的最大值加1。

fd_set *readfds:要进行监视的读文件集。

fd_set *writefds :要进行监视的写文件集。

fd_set *errorfds:用于监视异常数据。

struct timeval* timeout:select的超时时间,它可以使select处于三种状态:
*/
View Code

 理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节,fd_set中的每一bit可以对应一个文件描述符fd。则1字节长的fd_set最大可以对应8个fd。

  • (1)执行fd_set set; FD_ZERO(&set); 则set用位表示是0000,0000。
  • (2)若fd=5,执行FD_SET(fd,&set); 后set变为0001,0000(第5位置为1)
  • (3)若再加入fd=2,fd=1,则set变为0001,0011
  • (4)执行 select(6,&set,0,0,0) 阻塞等待
  • (5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。注意:没有事件发生的fd=5被清空。

 

posted @ 2022-09-14 17:56  ouyang_wsgwz  阅读(43)  评论(0编辑  收藏  举报