select和fd_set的理解

select函数如下:

int select(nfds, readfds, writefds, exceptfds, timeout);

其中readfds、writefds、exceptfds都是fd_set指针。

select需要将分离事件的socket放入各种事件集合,如果是连接事件和可读事件,放入readfds中。

 

fd_set结构如下:

typedef struct

  {

    /* XPG4.2 requires this member name.  Otherwise avoid the name

       from the global namespace.  */

#ifdef __USE_XOPEN

        __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];

# define __FDS_BITS(set) ((set)->fds_bits)

#else

        __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];

# define __FDS_BITS(set) ((set)->__fds_bits)

#endif

  } fd_set;

    针对fd_set的操作,设计了几个使用的宏。

FD_ZERO(&set);//将set的所有位置0

FD_SET(1, &set);// 将set的第1位置1,这样fd==1的文件描述字就被加进set中了

FD_CLR(4, &set);//将set的第4位置0,如set原来是10010000,则现在变为10000000,这样fd==4的文件描述字就被从set中清除了

FD_ISSET(5, &set);// 测试set的第5位是否为1,如果set原来是001100000,则返回非零,表明fd==5的文件描述字在set中;否则返回0 

每个需要分离事件的socket放入fd_set中占__fds_bits的一位,fds_bits一共1024位,设计成了长度为128的long int型数组。所里理论上select可以同时分离1024个目标socket的事件。

下面举例说明,例如创建的服务socket是3,将其放入readfds后,readfds->__fds_bits[0]就为8(1<<3),此时建立了一个连接socket 4,也将其放入readfds中,readfds->__fds_bits[0]就为24(1<<3|1<<4),以此类推。

select分离到事件之后,readfds->__fds_bits就为分离到事件的socket集合,返回值为分离到事件的socket的数量。例如分离到4号socket的可读事件,则select返回1,readfds->__fds_bits[0]为16(1<<4),如果select设置了超时时间,时间达到还是没有分离到任何事件,则返回0,readfds->__fds_bits也全为0。

上一篇:shell无名管道线的实现(父子进程实现对管道的一端读另一端写)


下一篇:学习:Linux之管道