当标准输入缓冲区中已有数据时,在标准输入上选择()
select函数阻塞调用进程,直到在任何指定的文件描述符集上有活动[...]如果读取调用不会阻塞,则认为文件描述符已准备好可供读取。 (请参阅:https://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html)
所以我期望,如果在第一次迭代中输入大于4个字符的字符串,那么在下面的程序中选择将立即返回第二个...迭代。 但事实并非如此。 在第一个输出后按任何其他键后,它将继续处理所有剩余的输入。 为什么?
示例输出:
./selectTest
12345678900
Keyboard input received: 1234
A
Keyboard input received: 5678
Keyboard input received: 900
Keyboard input received: A
码
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
int main(void)
{
fd_set rfds;
char buf[100];
while(1)
{
FD_ZERO(&rfds);
FD_SET(fileno(stdin), &rfds);
if(-1 == select(FD_SETSIZE, &rfds, NULL, NULL, NULL))
{
perror("select() failedn");
}
if(FD_ISSET(fileno(stdin), &rfds))
{
printf("Keyboard input received: ");
fgets(buf, 5, stdin);
printf("%sn", buf);
}
}
return 0;
}
(我知道,我不应该再使用select(),但我正在学习考试,我们必须......)
你正在阅读tty(4)(通常情况下,当stdin是你的终端时)。 这些都是棘手的事情,阅读tty揭秘。
请注意,你的终端和它的tty有一些线性规则。 所以,一些数据在内核中(也在标准库中)被缓冲。
您可能想要将您的tty置于原始模式。 参见termios(3)&stty(1)
但不要失去时间,而应使用像ncurses或readline这样的库
要使用select
,你可以使用一些fifo(7),也许使用mkfifo /tmp/myfifo
然后使用你的程序yourprogram < /tmp/myfifo
并在另一个终端中使用echo hello > /tmp/myfifo
基本上,问题在于你将缓冲的stdio流与低级I / O混合在一起。 select
被阻塞的原因是因为之前输入的数据已被读取并被缓存在stdin
的流数据缓冲区中。 尝试通过调用setbuf(stdin, NULL)
将stdin
设置为无缓冲模式。
上一篇: select() on stdin when there is already data in stdin's buffer