在我的Windows应用程序中,当从控制台阅读时,我使用WaitForSingleObject()
:
HANDLE h = (void*)GetStdHandle(STD_INPUT_HANDLE);
char buf[512] = { 0 };
DWORD r = 0;
if (WaitForSingleObject(h, 3000) == WAIT_OBJECT_0)
{
ReadConsole(h, buf, 512, &r, 0);
}
字符串
看起来,为了将上面的代码移植到Linux,我必须实现一个条件等待。我该如何实现这一点?如何在阅读某些字符之前检查它们是否已写入控制台?
1条答案
按热度按时间hrirmatl1#
与Windows代码非常类似的代码如下:
字符串
这使用了来自
#include <unistd.h>
和#include <poll.h>
的声明。poll()
函数等待指定文件描述符上的各种指定事件,并有一个以毫秒为单位的超时。-1
的超时值允许poll()
无限期等待(类似于Windows上调用WaitForSingleObject()
时的超时值INFINITE
)。成功完成后,它返回一个正值,表示有事件挂起的pollfd
结构的数量(即有一个非零的.revents
成员)。(也有可能在.revents
成员中报告一些特殊事件,而这些事件在.events
成员中没有被请求。)超时时,它返回0。如果出现错误,则返回-1
,errno
(由#include <errno.h>
定义)包含错误号。.revents
成员中的特殊事件包括POLLERR
(表示文件描述符发生错误)、POLLHUP
(表示文件描述符处于“挂起”状态)和POLLNVAL
(表示指定的文件描述符无效)。read()
函数调用可能会无限期阻塞,但如果文件描述符不是常规文件,则如果文件描述符已准备好读取(已在poll()
调用的结果中测试过),则通常不会阻塞。(也可以使用fcntl()
函数将底层文件置于非阻塞模式,在这种情况下,read()
将返回-1
,并将errno
设置为EAGAIN
,如果它没有准备好。poll()
不关心非阻塞模式。)成功时,read()
返回读取的字节数,该字节数可能小于请求的数量。(对于特殊文件,如果有一些数据可用,但少于请求的数量,它通常会返回可用的数据,而不是无限期地阻塞以尝试和读取请求的数量。)0
的返回值应被视为“文件结束”条件。(对于某些设备,例如终端,“文件结束”条件只是一个建议,是终端上某些特殊输入序列的结果。)失败时,read()
返回-1
并将errno
设置为错误号。对于来自终端的交互式输入,还有其他事情要考虑,例如终端的“termios”设置。除此之外,这些控制来自终端的输入何时准备好被读取的条件。在默认的“规范”模式下,输入将逐行就绪。在“非规范”模式下,输入是否就绪取决于其他参数,这些参数控制最小字符数和/或自上一个
read()
或上一个接收到的字符以来经过的时间。“termios”设置可以通过#include <termios.h>
声明的tcgetattr()
和tcsetattr()
函数进行查询和更改,并且只能在终端设备上工作。(#include <unistd.h>
声明的isatty()
函数可用于测试文件描述符是否引用终端。注意:除了
poll()
,你还可能会遇到更古老的select()
或pselect()
,它们用于等待文件描述符上的事件。它们将timeout参数作为指向struct timeval
的指针(对于select()
)或指向struct timespec
的指针(对于pselect()
)传递。select()
可以更新struct timeval
,以指示返回时还剩多少时间(但pselect()
* 不会 * 修改其struct timespec
)。