-2

当尝试从中读取 input_events 时,/dev/input/event16我注意到我正在读取的缓冲区的大小可能会导致异常。这是我写的代码:

    public static void main(String[] args) throws IOException{
        FileInputStream is = new FileInputStream("/dev/input/event16");
        byte[] three_bytes = new byte[3];
        byte[] twentyfour_bytes = new byte[24];
        is.read(three_bytes); // fails
        is.read(twentyfour_bytes); // does not fail

    }

我最初的实验表明,缓冲区至少需要一个完整input_event结构的容量。但我找不到原因。

问题是该行is.read(three_bytes); 导致以下异常:

Exception in thread "main" java.io.IOException: Invalid argument
        at java.base/java.io.FileInputStream.readBytes(Native Method)
        at java.base/java.io.FileInputStream.read(FileInputStream.java:249)
        at main.Test.main(Test.java:11)

我想弄清楚为什么该行在按预期读取数据 is.read(three_bytes);时抛出异常is.read(twentyfour_bytes);

4

1 回答 1

2

我想弄清楚为什么该行在按预期读取数据is.read(three_bytes);时会引发异常。is.read(twentyfour_bytes);

首先,/dev/input/event16不是一个常规文件。它是一个设备文件,设备文件的行为通常不像常规文件。

在这种情况下,/dev/input/event*设备文件用于从输入设备读取事件。当您对它们执行read系统调用时,它们将返回一个或多个完整事件。这些是二进制数据,其格式由以下 C 给出struct

struct input_event {    
    struct timeval time;    
    unsigned short type;
    unsigned short code;
    unsigned int value; 
};

不过,在典型的 64 位 Linux 系统上,该结构的大小(大概)是 24 字节。

我最初的实验表明,缓冲区至少需要一个完整input_event结构的容量。但我找不到原因。

事件设备的行为记录在Linux 输入驱动程序 v1.0的第 5 节中。它指出 aread将始终给出整数个input_event结构。

因此,read系统调用提供了一个小于 的缓冲区,sizeof(input_event)内核无法返回任何内容。显然,这会导致read系统调用以 errno value 失败EINVAL。(IMO,这是一个合理的设计选择,并且与文档中的含义一致EINVAL。)


因此,在 Java 中,当您调用read(three_bytes)时,它将映射到read读取大小为 3 字节的系统调用,但失败;看上面。系统调用失败通过 throw an 向 Java 应用程序发出信号IOException

于 2021-06-14T14:37:14.710 回答