Lseek SEEK_END 不工作?

Lseek SEEK_END not working?

我正在开发一个带有操纵杆的 C 程序,我想获取最后一个事件,即 js0 文件的最后一行。我试图将光标移到最后一个元素之前,但它似乎不起作用。知道为什么吗?

int fd = open ("/dev/input/js0", O_RDONLY);
struct js_event e;
lseek(fd, -(sizeof(e)), SEEK_END);    
read (fd, &e, sizeof(e));
switch(e.type){
    case JS_EVENT_BUTTON: printf("btn\n");
    break;
    case JS_EVENT_AXIS: printf("axes\n");
    break;
    default: printf("smth else\n");
}

我确定我正在阅读的文件至少有 (sizeof(e)) 长。 Lseek returns me -1 所以我得到了 errno,它是 29 - 非法搜索:为什么这是非法搜索?即使我使用 0 作为偏移量

,我也会得到相同的结果
  lseek(fd, 0, SEEK_END)

我使用的是最新版本 Ubuntu, 感谢您的帮助

why should this be an illegal seek?

您尝试读取的文件是一个字符特殊文件(这是其模式字符串第一个位置的 'c' 所指示的)内核的操纵杆驱动程序可以通过该文件与用户空间程序进行通信,例如作为你的。这样的文件就像管道——不可搜索。任何试图在这样的文件中寻找不同位置的尝试都会失败,并且一些 lseek() 实现可能会失败,即使参数对应于零净位置变化也是如此。您可以在此处找到有关设备文件的更多信息:What are character special and block special files in a unix system?

在评论里,你问

Any suggestion on how can I get last line?

,但这不太可能是您真正想要的。在这样一个表示通信通道的文件中,到达文件末尾(以便能够识别最后一行)表示通道已关闭并且已从中读取所有数据。 永远不会 通过该文件描述符获得更多数据。在一般情况下,您的情况不会发生这种情况。我怀疑这是你希望观察到的。

我想你想要的是发现操纵杆设备可用的最近事件,这在概念上很简单:你从设备读取事件直到读取块,或者会做。 The Linux kernel documentation for the device you're using 有一些避免无限期阻塞的建议:

  • 使用 select() 确定设备中的数据是否可用,然后再尝试从设备读取数据。

  • 以非阻塞模式打开设备(带有选项O_NONBLOCK),并为你的read()s做好准备失败 (returning -1) errno 设置为 EAGAIN.

请注意,在任何情况下,您都应该检查 read() 中的 return 值,并且至少存在一种不一定是真正错误的其他故障模式(EINTR).请阅读 its manual page 以及您正在使用的其他函数,了解诸如此类的详细信息。