gpt4 book ai didi

c++ - 为什么在这种情况下 stdin fd 还没有准备好

转载 作者:太空宇宙 更新时间:2023-11-04 10:10:18 25 4
gpt4 key购买 nike

根据 Linux Programmer's Manual , poll 可以等待一组文件描述符中的一个准备好执行 I/O。

据我了解,如果我将POLLIN 添加到eventspoll 将返回> 0整数,当至少有一个 fd 准备好被读取时。

考虑以下代码,在这段代码中,我希望程序在我键入字符 \n 后立即回显我的输入。

int main(){
char buffer[maxn];
while (true) {
struct pollfd pfd[1];
std::memset(pfd, 0, sizeof pfd);

pfd[0].fd = STDIN_FILENO;
pfd[0].events = POLLIN;

int ret = poll(pfd, 1, 1000);

if (ret < 0) {
}
else if (ret == 0) {
}
else {
if ((pfd[0].revents & POLLIN) == POLLIN) {
int n;
n = fscanf(stdin, "%s", &buffer);
if(n > 0){
printf("data from stdin: %s\n", buffer);
}
}else if((pfd[1].revents & POLLHUP) == POLLHUP){
break;
}
}
}
}

当我打字时

aa bb cc dd

我以为 fscanf 没有从标准输入中检索所有数据,因为它只读取 aa。所以当循环重新开始时,stdin 的 fd 应该仍然准备就绪。因此,(pfd[0].revents & POLLIN) == POLLIN 仍然有效,所以我认为我们可以看到以下输出

data from stdin: aa
data from stdin: bb
data from stdin: cc
data from stdin: dd

然而,实际上只打印了第一行。我在这里很奇怪,我认为这与 epollEdge-triggered mode 类似.但是,poll 是级别触发的。

那么您能解释一下为什么 fscanf 会发生这种情况吗?

最佳答案

轮询在文件描述符 级别进行,而fscanf在更高的文件句柄级别工作。

在较高级别,C 运行时库可以自由缓存输入流,这种方式会影响您在较低级别看到的内容。

例如(这可能就是这里发生的事情),你第一次fscanf你的话aa ,整个从文件描述符中读取并缓存,然后第一个单词返回给您。

后续fscanf (没有干预 poll )将首先检查缓存以获取下一个单词,如果不存在,它将返回到文件描述符以获取更多输入。

不幸的是,您在执行此操作之前检查轮询事件的事实会导致问题。就文件描述符 级别而言,整个 行已被您的第一个 fscanf 读取。所以没有进一步的输入可用 - poll因此将等到此类信息确实可用。

如果您更改:

n = fscanf(stdin, "%s", buffer);

进入:

n = read(STDIN_FILENO, buffer, 3);

并更改 printf到:

printf("data from stdin: %*.*s\n", n, n, buffer);

在那种情况下,您确实在按下 ENTER 键后立即得到了您期望的输出:

data from stdin: aa
data from stdin: bb
data from stdin: cc
data from stdin: dd

请记住,示例代码最多读取 三个 个字符(如 aa<space> )而不是一个单词。它更多地是为了说明问题是什么,而不是为您提供解决方案(以匹配您的问题“您能解释一下为什么会发生这种情况吗?”)。

当后者的缓存会影响前者时,解决方案是不要混合描述符和基于句柄的 I/O。

关于c++ - 为什么在这种情况下 stdin fd 还没有准备好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49476088/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com