Linux等效的WaitForSingleObject在从控制台读取时是什么?

huangapple go评论61阅读模式
英文:

Linux equivalent of WaitForSingleObject when reading a from console?

问题

在我的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,我需要实现条件等待。我该如何实现它?如何在读取之前检查是否已写入一些字符到控制台?

英文:

In my Windows application, I use WaitForSingleObject() when reading from a console:

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);
}

It looks like, in order to port the above code to Linux, I have to implement a conditional wait. How would I implement that? How can I check if some characters have been written to the console before reading them?

答案1

得分: 5

以下是翻译好的部分:

int h = STDIN_FILENO;
char buf[512] = { 0 };
ssize_t r = 0;
struct pollfd fds[1];
int ret;

fds[0].fd = h;
fds[0].events = POLLIN;
ret = poll(fds, 1, 3000);
if (ret > 0 && (fds[0].revents & POLLIN) != 0)
{
    r = read(h, buf, 512);
}

这段代码等价于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 设置为EAGAINpoll() 不关心非阻塞模式。)成功时,read() 返回读取的字节数,这可能小于请求的数量。(对于一些特殊文件,如果有一些可用数据,但少于请求的数量,通常会返回可用的数据,而不是无限期地阻塞以尝试读取请求的数量。)返回值为0应视为“文件结束”条件。(对于某些设备,例如终端,“文件结束”条件仅仅是一个建议,是终端上的某个特殊输入序列的结果。)失败时,read() 返回-1,并将errno 设置为错误号码。

对于从终端进行的交互式输入,还有其他要考虑的因素,例如终端的“termios”设置。除其他事项外,这些设置控制了何时可以读取来自终端的输入。在默认的“规范”模式下,输入以逐行方式准备就绪。在“非规范”模式下,输入准备就绪取决于其他参数,这些参数控制了最小字符数和/或自上次read() 或上次接收字符以来经过的时间。可以使用#include <termios.h> 声明的tcgetattr()tcsetattr() 函数查询和更改“termios”设置,仅适用于终端设备。(#include <unistd.h> 声明的isatty() 函数可用于测试文件描述符是否引用终端。)

英文:

A close equivalent to the Windows code is as follows:

    int h = STDIN_FILENO;
    char buf[512] = { 0 };
    ssize_t r = 0;
    struct pollfd fds[1];
    int ret;

    fds[0].fd = h;
    fds[0].events = POLLIN;
    ret = poll(fds, 1, 3000);
    if (ret &gt; 0 &amp;&amp; (fds[0].revents &amp; POLLIN) != 0)
    {
        r = read(h, buf, 512);
    }

This uses declarations from #include &lt;unistd.h&gt; and #include &lt;poll.h&gt;.

The poll() function waits for various specified events on specified file descriptors and has a timeout specified in milliseconds. A timeout value of -1 allows poll() to wait indefinitely (like a timeout value of INFINITE in calls to WaitForSingleObject() on Windows). On successful completion it returns a positive value indicating the number of pollfd structures that have events pending (i.e. have a non-zero .revents member). (It is also possible for some special events to be reported in the .revents member that were not asked for in the .events member.) On timeout it returns 0. On error it returns -1 and errno (defined by #include &lt;errno.h&gt;) contains the error number.

Special events in the .revents member include POLLERR (indicating an error has occurred on the file descriptor), POLLHUP (indicating a "hang-up" state on the file descriptor), and POLLNVAL (indicating the specified file descriptor is invalid).

The read() function call could block indefinitely, but if the file descriptor is something other than a regular file it typically does not block if the file descriptor is ready to be read (which has already been tested for in the results of the poll() call). (It is also possible to put the underlying file into non-blocking mode using the fcntl() function, in which case read() would return -1 and set errno to EAGAIN if it is not ready. poll() does not care about the non-blocking mode.) On success read() returns the number of bytes read which may be less than the requested amount. (For special files if there is some data available but less that the requested count, it typically returns what is available rather than blocking indefinitely to try and read the requested amount.) A return value of 0 should be treated as an "end-of-file" condition. (For some devices such as a terminal the "end-of-file" condition is merely a suggestion and is the result of some special input sequence on the terminal.) On failure read() returns -1 and sets errno to the error number.

For interactive input from a terminal, there are other things to consider such as the "termios" settings for the terminal. Amongst other things, these control the conditions when input from the terminal is ready to be read. In the default "canonical" mode, input becomes ready on a line-by-line basis. In "noncanonical" mode, input becomes ready depending on other parameters that control the minimum number of characters and/or the time elapsed since the previous read() or the previous received character. The "termios" settings can be queried and changed with the tcgetattr() and tcsetattr() functions declared by #include &lt;termios.h&gt; and only work on terminal devices. (The isatty() function declared by #include &lt;unistd.h&gt; can be used to test whether a file descriptor refers to a terminal.)


Note: Instead of poll() you may also encounter the more ancient select() or pselect() used for the same purpose of waiting for events on file descriptors. These pass the timeout parameter as a pointer to a struct timeval (for select()) or a pointer to a struct timespec (for pselect()). select() may update the struct timeval to indicate how much time was left when it returned (but pselect() does not modify its struct timespec).

huangapple
  • 本文由 发表于 2023年7月13日 21:47:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76680120.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定