在不停止代码的情况下使用 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 值来确定,如果如果您不考虑这一点,那么您可能会感到悲伤。但是,我认为您不会从操纵杆设备上看到任何简短的读数;你应该得到一个完整的事件或什么都没有。
我正在尝试使用 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 值来确定,如果如果您不考虑这一点,那么您可能会感到悲伤。但是,我认为您不会从操纵杆设备上看到任何简短的读数;你应该得到一个完整的事件或什么都没有。