在不停止代码的情况下使用 read() C 函数

Use read() C function without stopping code

我正在尝试使用 C 代码从操纵杆读取数据。我有 found online the way to do it.

这个解决方案似乎工作正常但有问题。当代码到达 read() 函数时,它停止并等待,直到操纵杆设备发生变化:

int read_event(int fd, struct js_event *event)
{
    ssize_t bytes;

    bytes = read(fd, event, sizeof(*event));
    if (bytes == sizeof(*event))
        return 0;
    return -1;
}

我正在尝试找到一种方法使代码 运行 连续,如果控制设备没有变化,只是 return 以前的状态。到目前为止我没有成功。也许有人可以提供帮助。

我不确定实际的 API(系统调用)函数,但我的想法应该可行。

使用类似 GetNumberOfInputEvents(WinAPI 函数)的方法来确定您的读取是否会卡住(没有可读取的内容)。然后如果你判断会卡,就跳过

有关详细信息,请参阅 Checking the stdin buffer if it's empty

伪代码:

read_event(Event* event){
    if (is_event_buffer_empty())
        // Do nothing because `read` is stuck
    else
        SystemAPI_ReadEvent(event);
}

鉴于您通过 open() 打开操纵杆设备并通过 read() 从中读取,我推断您正在为实现 POSIX 接口的机器编码。对于大多数文件,POSIX read() 函数会阻塞,直到它可以传输至少一个字节,这确实是您观察到的行为。

避免这种情况的一种方法是以非阻塞模式打开文件,或者在打开文件后读取文件之前将其置于非阻塞模式。您可以通过在打开的选项中添加 O_NONBLOCK 标志来实现前者:

 js = open(device, O_RDONLY | O_NONBLOCK);

这应该与您现有的读取操纵杆事件的代码进行干净且有利的交互。如果没有事件可供读取,您的 read() 调用应立即 return,return 值为 -1,并且 errno 设置为 EAGAIN。否则,它将 return 传输的字节数。

请注意,一般来说,read() 不能保证传输您请求的全部字节数——它可能会成功读取更少的字节数,您可以从它的 return 值来确定,如果如果您不考虑这一点,那么您可能会感到悲伤。但是,我认为您不会从操纵杆设备上看到任何简短的读数;你应该得到一个完整的事件或什么都没有。