According to this article poll vs select vs event-based:
select() only uses (at maximum) three bits of data per file
descriptor, while poll() typically uses 64 bits per file descriptor.
In each syscall invoke poll() thus needs to copy a lot more over to
kernel space. A small win for select().
Here is the implementation of fd_set (found on Advisories : multiple applications fd_set structure bitmap array index overflow
#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
So, in the end, fd_set is just an array of long. It is also written:
A call to FD_SET sets a bit to 1 using socket number as an index:
which means, if I got a socket fd number 5, the element indexed 5 will be seleted, and its first bit will be flipped from 0 to 1. Since select() uses 3 bits, I guess the other two bits are for sending and receive. Is this correct? Why does select() use a long when it only needs 3 bits?
Also, stated above, poll() uses 64 bits for checking. Why does poll need to check every bit in pollfd struct? Here is the pollfd struct:
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
};
The total bits in the struct is 64 bits, for a 32-bit int and two 16-bit short. I know the usual way of checking a bit flag is using AND (&) operator to filter out other irrelevant bits. Does that apply to this case?
It doesn’t use 1
longper se. It uses a bit field ofFD_SETSIZEbits, in this case 32 32 bits longs or 16 64 bits longs. By using longs, it allows to use less memory operations on 64 bit machines (which are widespread on Unix already for 20 years). They could have used normalintbut then they wouldn’t have had an advantage on 64 bit machines. It’s only forward thinking.If you used select on several file descriptors you need the room for all the file descriptors. Imagine you want to read from 3 sockets, from a SCSI device and a file and the file descriptor values are respectively 3, 7, 10, 12 and 67, how would you represent that? Use a bitset where the bit with that number is set.