详解fd_set结构体

在使用select函数时,就免不了要遇到fd_set结构体。那我们就来深入研究下fd_set的结构体!

//
首先,我们来看下下面几个函数!
Alt
这几个函数都有用到fd_set类型的数据,我们就会想这个到底是种什么类型的数据!下面来一步步来看个究竟

在/usr/include/sys/select.h中

typedef long int __fd_mask;


/* It's easier to assume 8-bit bytes than to get CHAR_BIT. */
#define __NFDBITS (8 * (int) sizeof (__fd_mask))
#define __FDELT(d) ((d) / __NFDBITS)
#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS))

/* fd_set for select and pselect. */
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;

/* Maximum number of file descriptors in `fd_set'. */
#define FD_SETSIZE __FD_SETSIZE   //__FD_SETSIZE等于1024

/* Access macros for `fd_set'.  */
#define FD_SET(fd, fdsetp)      __FD_SET (fd, fdsetp)
#define FD_CLR(fd, fdsetp)      __FD_CLR (fd, fdsetp)
#define FD_ISSET(fd, fdsetp)    __FD_ISSET (fd, fdsetp)
#define FD_ZERO(fdsetp)         __FD_ZERO (fdsetp)

从上面的代码中简化下来,其实可以改成

typedef struct{
    long int fds_bits[32];
}fd_set;

其实fd_set就是一个long int类型的数组。因为每一位可以代表一个文件描述符。所以fd_set最多表示1024个文件描述符!

在 /usr/include/bit/select.h中

# define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d))
# define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d))
# define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d))

通过查看这几个源码,我们就可以知道这几个函数的实现!现在我就跟踪下FD_SET(fd, fdsetp)这个函数的实现

#define FD_SET(fd, fdsetp)      __FD_SET (fd, fdsetp)

# define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d))

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

#define __FDELT(d) ((d) / __NFDBITS)

#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS))

将上面的函数化简下,就可以得到

#define FD_SET(fd,fdsetp)  fdsetp->__fds_bits[fd/32] |= (long int)1<<(d%32)

也就是将相应的位进行置位!

下面我们通过代码来对我们的结果进行验证!

#include <sys/select.h>

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main(void)
{
    fd_set set;

    FD_ZERO(&set);

    int i;
    for(i = 0;i < 32;i++)
    {
        printf("set.__fds_bits[%d]:%ld\t",i,set.__fds_bits[i]);
    }
    printf("\n/\n");
    FD_SET(10,&set);
    for(i = 0;i < 32;i++)
    {
        printf("set.__fds_bits[%d]:%ld\t",i,set.__fds_bits[i]);
    }
    
    printf("\n/\n");
    FD_ZERO(&set);
    FD_SET(32,&set);
    for(i = 0;i < 32;i++)
    {
        printf("set.__fds_bits[%d]:%ld\t",i,set.__fds_bits[i]);
    }
}

FD_SET(10,&set);将set的第十位置一,也就是set.__fds_bits[0]为1024!
FD_SET(32,&set);将set的第32位置一,也就是set.__fds_bits[1]为1!
执行结果如下:

Alt

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值