what is select?
#include <sys/select.h> #include <sys/time.h> int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout) 返回值:就绪描述符的数目,超时返回0,出错返回-1
example
例子1, 最简单的官方select例子。
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
int main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
else if (retval)
printf("Data is available now.\n");
/* FD_ISSET(0, &rfds) will be true. */
else
printf("No data within five seconds.\n");
exit(EXIT_SUCCESS);
}
编译&&运行
#编译
gcc ./test_select.c -o test_select
#创建命名管道
mkfifo myfifo
#运行test_select, 将命名管道作为stdin
./test_select < myfifo
#往命名管道中写入字符
echo "aaa" >> myfifo
#查看打印结果
$ ./test_select < myfifo
Data is available now.
当然如果你在linux电脑上,可以找到直接向下面的目录写入内容,作为stdin
echo "aaa" >> /proc/<你的进程的pid>/fd/0
例子2,多路io的例子
// test_select.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s file...\n", argv[0]);
exit(EXIT_FAILURE);
}
int nfds, num_open_fds;
num_open_fds = nfds = argc - 1;
int fds[num_open_fds];
printf("size of fds = %lu, num_open_fds = %d\n", sizeof(fds), num_open_fds);
memset(fds, 0, sizeof(fds));
for (int j = 0; j < nfds; j++) {
fds[j] = open(argv[j + 1], O_RDONLY|O_NONBLOCK);
if (fds[j] == -1)
errExit("open");
printf("Opened \"%s\" on fd %d\n", argv[j + 1], fds[j]);
}
// 设置监听的文件操作符
fd_set rfds;
struct timeval tv;
int retval;
tv.tv_sec = 10;
tv.tv_usec = 0;
while(1) {
// 每次都要重新设置,因为select的返回会修改rfds
FD_ZERO(&rfds);
int maxfd = 0;
for (int j = 0; j < nfds; j++) {
FD_SET(fds[j], &rfds);
if (fds[j] > maxfd)
maxfd = fds[j];
}
retval = select(maxfd + 1, &rfds, NULL, NULL, &tv);
if (retval == -1)
perror("select()");
else if (retval) {
printf("Data is available now.\n");
for (int j = 0; j < nfds; j++) {
printf("fds[%d] in set: %s\n", j, FD_ISSET(fds[j], &rfds) ? "true" : "false");
if (FD_ISSET(fds[j], &rfds)) {
// 读取Input字符串
char buf[10];
ssize_t s = read(fds[j], buf, sizeof(buf));
if (s == -1)
errExit("read");
printf(" read %zd bytes: %.*s\n", s, (int) s, buf);
}
}
}
else
printf("No data within five seconds.\n");
}
exit(EXIT_SUCCESS);
}
编译&&运行&&测试
#编译
gcc ./test_select.c -o test_select
#创建两个命名管道
mkfifo myfifo1 myfifo2
#运行
./test_select myfifo1 myfifo2
#在另外一个终端往fifo中写入字符串
echo "aaa" >> myfifo1
#查看结果
结果如下:
$ ./test_select myfifo1 myfifo2
size of fds = 8, num_open_fds = 2
Opened "myfifo1" on fd 3
Opened "myfifo2" on fd 4
Data is available now.
fds[0] in set: true
read 4 bytes: aaa
fds[1] in set: false
Data is available now.
fds[0] in set: true
read 0 bytes:
fds[1] in set: false
Data is available now.
fds[0] in set: false
fds[1] in set: true
read 4 bytes: aaa
Data is available now.
fds[0] in set: false
fds[1] in set: true
read 0 bytes:
No data within five seconds.
No data within five seconds.
No data within five seconds.
No data within five seconds.
No data within five seconds.
No data within five seconds.
No data within five seconds.
No data within five seconds.
No data within five seconds.
No data within five seconds.