如何在 select 中使用 fd_set 检查位掩码?

Amu*_*umu 2 c bit-manipulation

根据这篇文章民意调查 vs 选择 vs 基于事件

select() 每个文件描述符仅使用(最多)3 位数据,而 poll() 通常每个文件描述符使用 64 位数据。因此,在每个系统调用中调用 poll() 都需要将更多内容复制到内核空间。select() 的一个小胜利。

这是fd_set的实现(在Advisories上找到:多个应用程序fd_set结构位图数组索引溢出

#ifndef FD_SETSIZE
#define FD_SETSIZE  1024
#endif
#define NBBY    8       /* number of bits in a byte */
typedef long    fd_mask;
#define NFDBITS (sizeof (fd_mask) * NBBY)   /* bits per mask */
#define howmany(x,y)    (((x)+((y)-1))/(y))
typedef struct _types_fd_set {
    fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
} _types_fd_set;

#define fd_set _types_fd_set
Run Code Online (Sandbox Code Playgroud)

所以,最终,fd_set只是一个long. 书中还写道:

对 FD_SET 的调用使用套接字号作为索引将一位设置为 1:

这意味着,如果我得到一个套接字 fd 编号为 5,则索引为 5 的元素将被选择,并且其第一位将从 0 翻转到 1。由于select()使用 3 位,我猜其他两位用于发送和接收。它是否正确?为什么要select()使用 long,而它只需要 3 位?

另外,如上所述,poll()使用 64 位进行检查。为什么poll需要检查pollfd结构体中的每一位?这是pollfd结构:

struct pollfd {
    int fd;         // the socket descriptor
    short events;   // bitmap of events we're interested in
    short revents;  // when poll() returns, bitmap of events that occurred
};
Run Code Online (Sandbox Code Playgroud)

该结构体中的总位为 64 位,其中一个 32 位 int 和两个 16 位 Short。我知道检查位标志的常用方法是使用AND (&)运算符过滤掉其他不相关的位。这适用于本案吗?

jør*_*sen 5

poll() 通常每个文件描述符使用 64 位。因此,在每个系统调用中调用 poll() 都需要将更多内容复制到内核空间。select() 的一个小胜利。

谬论——如果你只想监视一个 fd,poll(2) 会让你摆脱这 64 位,而对于 select(),你必须复制最多 12288 位(3 组,通常每组 4096 位)。

另外,poll() 支持大于 FD_SETSIZE 值的fd 。