我正在编写一个程序,它使用函数 fgets 从标准输入循环读取,如下所示:
while(fgets(buffer2, BUFFERSIZE , stdin) != NULL){
//Some code
}
我希望我的代码是非阻塞的,即:当用户目前没有输入时,我不希望程序停留在“fgets”行上。
我该怎么做?
我正在编写一个程序,它使用函数 fgets 从标准输入循环读取,如下所示:
while(fgets(buffer2, BUFFERSIZE , stdin) != NULL){
//Some code
}
我希望我的代码是非阻塞的,即:当用户目前没有输入时,我不希望程序停留在“fgets”行上。
我该怎么做?
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 并为你设置一个错误代码。
如果您有适当的 POSIX 环境,则可以在调用...之前使用select()
或poll()
检查stdin
' 描述符上的输入。fgets()
read()
Jan 在下面的评论(谢谢!)解释了为什么你不能使用fgets()
这种方法......总之,对象中有一个额外的缓冲层,尽管在文件描述符上找不到更多内容FILE
,但数据已经可以等待了。 select()
. 阻止您的程序及时响应,如果其他系统在发送更多数据之前等待对已发送数据的响应,则可能会挂起stdin
。
你基本上有两个选择:
在 Linux 上,您可以通过按ctrl-d来指定输入的结束,当然您也可以使用单独的线程来执行此操作。
这听起来有点矫枉过正,但这是我想到的。
使用 2 个不同的线程 - 一个使用此循环并等待阻塞(我认为这不能非阻塞地完成)。当读取某些内容时,将其推入管道。
同时,另一个线程将做它需要做的任何事情并不时检查管道中的数据(显然,你希望这是异步的,或者至少我是这样理解的。如果是这样,这意味着不同的线程)
但是,您需要很好地同步两个线程。你应该检查你的操作系统关于多线程和 IO 操作。