2

我正在编写一个程序,它使用函数 fgets 从标准输入循环读取,如下所示:

while(fgets(buffer2, BUFFERSIZE , stdin) != NULL){
  //Some code  
}

我希望我的代码是非阻塞的,即:当用户目前没有输入时,我不希望程序停留在“fgets”行上。
我该怎么做?

4

5 回答 5

4

fgets()是一个阻塞函数,它意味着等待直到数据可用。

如果要执行异步 I/O,可以使用select()poll()epoll()。然后在有可用数据时从文件描述符中执行读取。

这些函数使用 FILE* 句柄的文件描述符,通过以下方式检索:

int fd = fileno(f);

如果您使用的是 Unix 或 Linux,那么一种解决方案是将文件使用的文件描述符标记为非阻塞。例子:

#include <fcntl.h>  
FILE *handle = popen("tail -f /als/als_test.txt", "r"); 
int fd = fileno(handle);  
flags = fcntl(fd, F_GETFL, 0); 
flags |= O_NONBLOCK; 
fcntl(fd, F_SETFL, flags); 

fgets现在应该是非阻塞的,并且会返回一个 null 并为你设置一个错误代码。

于 2011-05-19T08:23:02.620 回答
2

如果您有适当的 POSIX 环境,则可以在调用...之前使用select()poll()检查stdin' 描述符上的输入。fgets()read()

Jan 在下面的评论(谢谢!)解释了为什么你不能使用fgets()这种方法......总之,对象中有一个额外的缓冲层,尽管在文件描述符上找不到更多内容FILE,但数据已经可以等待了。 select(). 阻止您的程序及时响应,如果其他系统在发送更多数据之前等待对已发送数据的响应,则可能会挂起stdin

于 2011-05-19T08:22:20.227 回答
1

你基本上有两个选择:

  1. 在单独的线程中运行该循环。
  2. 检查您的操作系统是否支持某些用于非阻塞 IO 的 API。
于 2011-05-19T08:20:40.707 回答
0

在 Linux 上,您可以通过按ctrl-d来指定输入的结束,当然您也可以使用单独的线程来执行此操作。

于 2011-05-19T08:35:23.227 回答
0

这听起来有点矫枉过正,但这是我想到的。

使用 2 个不同的线程 - 一个使用此循环并等待阻塞(我认为这不能非阻塞地完成)。当读取某些内容时,将其推入管道。

同时,另一个线程将做它需要做的任何事情并不时检查管道中的数据(显然,你希望这是异步的,或者至少我是这样理解的。如果是这样,这意味着不同的线程)

但是,您需要很好地同步两个线程。你应该检查你的操作系统关于多线程和 IO 操作。

于 2011-05-19T08:21:24.307 回答