linux select()系统调用如何监视两个文件(文件描述符)以及如何使用计时器参数

linux select()系统调用如何监视两个文件(文件描述符)以及如何使用计时器参数,c,linux,C,Linux,我需要使用select系统调用,在这里我必须打开两个文件描述符并对准备好的文件执行读取操作,我需要在每5毫秒后使用一些超时并读取这些文件 以下是我的示例代码: int main() { fd_set readfds,writefds; ssize_t nbytes,bytes_read; char buf[20]; int fd_1,fd_2,retval; struct timeval tv; fd_1 = open("test1.txt",

我需要使用select系统调用,在这里我必须打开两个文件描述符并对准备好的文件执行读取操作,我需要在每5毫秒后使用一些超时并读取这些文件 以下是我的示例代码:

int main()
{

    fd_set readfds,writefds;
    ssize_t nbytes,bytes_read;
    char buf[20];
    int fd_1,fd_2,retval;
    struct timeval tv;

    fd_1 = open("test1.txt", O_RDWR);
    if(fd_1 < 0) {
        printf("Cannot open file...\n");
        return 0;
    }

    fd_2 = open("test2.txt", O_RDWR);
    if(fd_2 < 0) {
        printf("Cannot open file_2...\n");
        return 0;
    }

    /* Wait up to five seconds. */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

    for(;;)
    {
        retval = select(FD_SETSIZE, &readfds, &writefds, NULL, &tv);
        printf("select");
        perror("select");
        exit(EXIT_FAILURE);

        //}
        for(int i=0; i < FD_SETSIZE; i++)
        {
            FD_ZERO(&readfds);
            if (FD_ISSET(i, &readfds))
            {
                // read call happens here //
                nbytes = sizeof(buf);
                bytes_read = read(i, buf, nbytes);
                printf("%ld", bytes_read);
            }
            else
            {
                perror("read");
                exit(EXIT_FAILURE);
            }
        }
    }

在调用select之前,需要初始化文件描述符集。使用当前代码,select以EBADF结束

像这样的东西应该可以做到:

FD_ZERO (&writefds);

for(;;)
{
    FD_ZERO (&readfds);
    FD_SET(fd_1, &readfds);
    FD_SET(fd_2, &readfds);

    retval = select(FD_SETSIZE, &readfds, &writefds, NULL, &tv);
    if (retval < 0) {
        perror("select");
        exit(EXIT_FAILURE);
    }

    for(int i=0; i<FD_SETSIZE; i++)
    {
        if (FD_ISSET(i, &readfds))
        {
            // read call happens here //
            printf("reading from file: %d\n", i);

            nbytes = sizeof(buf);
            bytes_read = read(i, buf, nbytes);
            printf("read %ld bytes\n", bytes_read);
        }
    }
}
你也可以检查一下;;循环并仅在出现错误时退出。一旦select行为正常,就可以在第二个for循环内继续调试。这里似乎不使用writefds,所以您也可以在select中将其设置为NULL


还有一个注意事项:由于读取集中只有两个文件,您只需检查FD_ISSETfd_1/FD_ISSETfd_2,而不是迭代所有FD_SETSIZE条目。

请,以您的示例代码为例,我尝试了这种方法,但我无法通过这些文件描述符来选择系统调用stuck@rupsum_1998我不太明白。你说你不能通过这些考试是什么意思?具体发生了什么?例如,如果有两个文件描述符,fd_1表示一个文本文件,fd_2表示另一个文本文件,因此select系统调用应该找到哪个进程已准备就绪,并对该文件执行读取操作。这是我无法执行的操作。@rupsum1998。但首先需要在readfds集合中添加这两个文件描述符,如上面的代码示例所示。然后检查select的返回值,如果成功,则进入第二个循环并检查哪些FD已准备好读取。但也不要在检查之前用FD_ZERO擦除您的ReadFD…我尝试了您所说的将FD_1和FD_2添加到readfds的方式,但仍然没有区别。请按照您所说的方式编写代码,如果可能的话,发布示例代码,这将有助于我的理解。