系统调用之select

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.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值