【问题标题】:Use read() C function without stopping code在不停止代码的情况下使用 read() C 函数
【发布时间】:2017-08-04 14:36:06
【问题描述】:

我正在尝试使用 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;
}

我试图找到一种方法让代码连续运行,如果控制设备没有变化,就返回之前的状态。到目前为止,我没有成功。也许有人可以帮忙。

【问题讨论】:

  • 你是如何opened 文件描述符的?
  • 2 个选项 - select(2) 或线程。
  • @EugeneSh。我打开它: device = "/dev/input/js0"; js = 打开(设备,O_RDONLY);与原始链接一样。
  • @JanusGowda read() 阻塞是正常的,直到它可以传输至少一个字节,除了以非阻塞模式打开的文件。通过在传递给open() 的选项位掩码中包含标志O_NONBLOCK,您应该能够以非阻塞模式打开设备。
  • @JanusGowda 是的,读取等待直到有数据可供读取。

标签: c joystick


【解决方案1】:

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

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

 js = open(device, O_RDONLY | O_NONBLOCK);

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

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

【讨论】:

    【解决方案2】:

    我不确定实际的 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);
    }
    

    【讨论】:

    • 这是非常错误的。因为在is_event_buffer_empy() 之后数据可能会变得不可用 - 其他线程正在读取它。
    • OP 正在通过文件描述符读取,而不是流,因此没有流缓冲区(除非他自己实现)。即使有,缓冲区为空与没有数据可供读取是不同的。
    猜你喜欢
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多