FD_ISSET的工作原理是什么?

4
该手册说明FD_ISSET检查套接字是否在集合中。因此,我认为条件if (FD_ISSET(STDIN, &readfds))应该立即打印输出,如果stdin在集合中,但实际上它会等待我按enter键。我错了什么?是不是当程序调用FD_SET(STDIN, &readfds)时,stdin已经被设置好了
为什么如果我输入的是其他字符而不是enter键,控制台会返回命令未找到?我认为这些字符应该像我使用fgets时输入的任何其他字符一样被处理。
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#define STDIN 0  // file descriptor for standard input

int main(void)
{
    struct timeval tv;
    fd_set readfds;

    tv.tv_sec = 2;
    tv.tv_usec = 500000;

    FD_ZERO(&readfds);
    FD_SET(STDIN, &readfds);

    // don't care about writefds and exceptfds:
    select(STDIN+1, &readfds, NULL, NULL, &tv);

    if (FD_ISSET(STDIN, &readfds))
        printf("A key was pressed!\n");
    else
        printf("Timed out.\n");

    return 0;
}

1
你期望 select 等待什么?请注意,此系统调用会重用输入集作为输出。 - doynax
所以选择块,只有当我按下回车键时才运行条件? - PMH
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - twalberg
2
@PMH:明确一点,select 不是特别等待回车键。相反,它在等待你要求的 STDIN 输入,而在 cooked 模式下,控制台会缓冲整行并一次性传递。 - doynax
1
@PMH:在select的输入中,读取集合指定等待的文件描述符集合,而在返回时则返回具有可读输入的子集描述符。如果您等待超时,则标准输入上没有可读内容,因此标志将被清除。 - doynax
显示剩余7条评论
1个回答

3

选择操作会等待按下回车键或超时。 你会感觉FD_ISSET正在等待回车键,因为选择操作已经超时。

如果检查返回值(retval),你会更好地理解。

struct timeval tv; 
fd_set readfds;
int retval;

tv.tv_sec = 2;
tv.tv_usec = 500000;

FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);

// don't care about writefds and exceptfds:
printf ("before select \n" );
retval = select(STDIN+1, &readfds, NULL, NULL, &tv);
printf ("after select \n" );

if (retval == -1) 
    perror("select()");
else if (retval > 0)
{
    //if (FD_ISSET(STDIN, &readfds));
        printf("Data is available now.\n");
}   
else
    printf("No data . timedout \n");

你能确认当超时发生时,所有的文件描述符都会从集合中移除吗? - PMH
是的。你只需要在 return 前面再加一个 select,你就会发现它会在超时时被清除。 - resultsway

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接