在使用select
函数进行I/O多路复用时,FD_SET()
宏的作用是向一个fd_set
类型的文件描述符集合中添加你感兴趣的文件描述符。这个操作非常重要,因为select
函数正是基于这个集合来监控哪些文件描述符已经准备好进行读、写或异常处理的。
当你调用select
时,它会检查fd_set
集合中所有的文件描述符,看它们是否满足你设定的条件(例如是否可读、可写或有异常)。如果没有文件描述符准备好,select
会阻塞,直到至少有一个文件描述符准备好或超时。
FD_SET()
、FD_CLR()
、FD_ISSET()
和FD_ZERO()
这一系列宏是用来操作fd_set
集合的:
FD_ZERO(fd_set *set)
:清空集合,将所有位设置为0,表示集合中没有任何文件描述符。FD_SET(int fd, fd_set *set)
:将指定的文件描述符fd
添加到集合set
中。FD_CLR(int fd, fd_set *set)
:从集合set
中移除指定的文件描述符fd
。FD_ISSET(int fd, const fd_set *set)
:检查文件描述符fd
是否在集合set
中,如果在则返回非零值,否则返回0。
当你调用select
后,select
会返回一个整数值,表示集合中有多少个文件描述符已经准备好。这个数字不一定等于你最初放入集合中的文件描述符总数,因为它只表示那些状态发生变化的描述符数量。你可以通过再次使用FD_ISSET()
宏来检查哪些具体的文件描述符已经准备好了。
例如,如果你有三个文件描述符fd1
、fd2
和fd3
,并且你只对fd1
和fd2
感兴趣,那么你应该只用FD_SET()
将fd1
和fd2
添加到集合中。当select
返回时,即使fd3
也准备好了,但因为你没有监控它,select
不会报告它的状态变化。
简而言之,FD_SET()
用于指定你关心的文件描述符,而select
函数基于这个集合来检测这些描述符的状态变化,返回准备好的描述符数量,以及通过修改集合来指示哪些描述符已经准备好。这使得select
能够有效地监控多个文件描述符,而无需为每个描述符创建独立的线程或进程。