select
函数是用于多路复用 I/O 的系统调用,它可以同时监视多个文件描述符的可读、可写和错误事件。在 Linux 系统中,select
函数的用法如下:
#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
参数说明:
nfds
:要检查的最大文件描述符值加 1。readfds
:可读性检查的文件描述符集合。writefds
:可写性检查的文件描述符集合。exceptfds
:异常情况检查的文件描述符集合。timeout
:超时时间。
返回值:
- 如果有事件发生,则返回就绪文件描述符的总数。
- 如果超时时间到达而没有任何事件发生,则返回 0。
- 如果发生错误,则返回 -1,并设置
errno
。
在使用 select
函数之前,需要对文件描述符集合进行初始化和设置。可以使用以下宏函数来操作文件描述符集合:
FD_ZERO(fd_set *set)
:将指定的文件描述符集合清空。FD_SET(int fd, fd_set *set)
:将指定的文件描述符添加到集合中。FD_CLR(int fd, fd_set *set)
:将指定的文件描述符从集合中移除。FD_ISSET(int fd, fd_set *set)
:判断指定的文件描述符是否在集合中。
下面是一个简单的示例代码,展示了 select
函数的用法:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
fd_set readfds;
struct timeval timeout;
// 清空文件描述符集合
FD_ZERO(&readfds);
// 添加标准输入文件描述符到集合中
FD_SET(STDIN_FILENO, &readfds);
// 设置超时时间为 5 秒
timeout.tv_sec = 5;
timeout.tv_usec = 0;
// 监听文件描述符集合
int result = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &timeout);
if (result == -1) {
perror("select");
exit(EXIT_FAILURE);
} else if (result == 0) {
printf("Timeout occurred.\n");
} else {
if (FD_ISSET(STDIN_FILENO, &readfds)) {
printf("Data is available to read.\n");
}
}
return 0;
}
上述代码通过 select
函数监听标准输入文件描述符(STDIN_FILENO
),并设置了 5 秒的超时时间。如果在超时时间内有数据可读,则输出 "Data is available to read.";否则,在超时时间到达时输出 "Timeout occurred."。