在循环和多个操作中使用 select 系统调用

Using select system call in a loop and multiple operations

我正在尝试向串行端口文件写入和读取数据/dev/ttyUSB0,如果操作在 5 秒内不成功,我将继续。为了实现这一点,我选择使用 select() 系统调用。但是,我使用它的确切情况似乎无法按预期工作。以下代码:

简单地说,我需要检查 8 台设备 的状态。所以我必须先write()一个查询命令。然后等待设备的响应 timeout 秒。

应该对 UART 上连接的所有 8 个设备执行此过程。 我不确定是否必须重新初始化 fdset 才能使用 select。

结果:第一次 select 等待 5 秒超时。但之后它立即显示 "timeout" 没有等待。

struct timeval timeout; 
timeout.tv_sec = 5;
timeout.tv_usec = 10;

for(i=0; i <= noOfDevicesDiscovered; i++)
{
    if( i < 9 && i > 0)
                {
                    uart_init();
                    printf("ID: %d\n", i);
                    address = ((i-1)<<1) | 0x01;
                    command = 0xA0;
                    fd_set set;
                    FD_ZERO(&set); 
                    FD_SET(uart_fd, &set); 


                    write(uart_fd, &address, 1);
                    write(uart_fd, &command, 1);

                    rv = select(uart_fd + 1, &set, NULL, NULL, &timeout);
                    if(rv == -1)
                        perror("select\n"); 
                    else if(rv == 0)
                    {
                        printf("timeout\n");
                        new.level = 0;
                        new.address = i;
                        fwrite(&new, sizeof(struct Light_Info), 1, fptr);
                        continue;
                    }
                    else
                    {
                        read( uart_fd, &level, 1 ); 
                        new.level = level;
                    }

                    new.address = i;
                    fwrite(&new, sizeof(struct Light_Info), 1, fptr);   
                    close(uart_fd);
                    FD_ZERO(&set); 
                }
}

我们如何解决这个问题。

您需要在每次调用 select 后重新初始化 "timeout"。来自 select 手册页; "On Linux, select() modifies timeout to reflect the amount of time not slept"。所以在你的情况下,在第一次 select 调用之后,你的超时值都是 0。因此对 select 的后续调用将立即超时。