IOCTL 编号可能与 C IOCTL 编号不同

  • 本文关键字:IOCTL 编号 python ioctl fcntl
  • 更新时间 :
  • 英文 :


我所知,ioctl 编号由驱动程序很好地定义并在内核中注册。

我正在用python使用一些代码来查询操纵杆状态。我已经阅读了这个关于操纵杆 API 的文档,这个关于 ioctl 数字的文档,以及这个来自 python fcntl 模块的文档。

我创建了一个用于测试和查询值的 C 程序,并使用我从这里获取的代码进行 python 测试,以实现 _IOR() C 宏。

内核驱动程序定义:

monolith@monolith ~/temp $ grep JSIOCGAXES /usr/include/* -r
/usr/include/linux/joystick.h:#define JSIOCGAXES        _IOR('j', 0x11, __u8)

C 程序

#include <stdio.h>
#include <linux/joystick.h>
#include <fcntl.h>
int main() {  
  int fd = open("/dev/input/js0", O_RDONLY);
  printf("Ioctl Number: (int)%d  (hex)%xn", JSIOCGAXES, JSIOCGAXES);
  char number;
  ioctl(fd, JSIOCGAXES, &number);
  printf("Number of axes: %dn", number);
  close(fd);
  return 0;
}

C 程序输出:

monolith@monolith ~/temp $ ./test 
Ioctl Number: (int)-2147390959  (hex)80016a11
Number of axes: 6

蟒蛇输出

# check if _IOR results in the used ioctl number in C
>>> _IOR(ord('j'), 0x11, 'c')
-2147390959
>>> file = open("/dev/input/js0")
# use that integer
>>> fcntl.ioctl(file, -2147390959)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 14] Bad address
# ask what hex value is
>>> "%x" % -2147390959
'-7ffe95ef'
# WHY THIS HEX CONVERSION DIFFERS?
>>> fcntl.ioctl(file, -0x7ffe95ef)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 14] Bad address
# Use the hex value from the C program output
>>> fcntl.ioctl(file, 0x80016a11)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 14] Bad address

知道为什么我不能使用该 ioctl 编号查询文件描述符的任何想法? ioctl()fcntl()函数采用文件描述符或实现fileno()方法的对象,因此我将错误与file对象分开。

也许问题出在数字转换和类型上,不知道...蛛丝马迹?

这一切都归结为十六进制转换不同 - 插入十六进制 C 会给你一个不同的数字:

>>> 0x80016a11
2147576337

我不确定为什么 Python 和 C 给出不同的十六进制,但它可能至少部分与符号相关 - Python 的'%x'给出有符号十六进制值 1,printf s 给出无符号值 2。

使用

Python 的十六进制值 ( -7ffe95ef ( 可能会改善事情 - 或者,更好的是,像在 C 中那样使用变量并避免转换错误:

op = _IOR(ord('j'), 0x11, 'c')
...
fcntl.ioctl(file, op)

我将回答我自己的问题。

出于某种原因,使用 python ioctl()获取值的唯一方法是发布以下代码:

>>> buf = array.array('h', [0])
>>> fcntl.ioctl(file.fileno(), 0x80016a11, buf)
0
>>> buf[0]
6

也就是说,使用缓冲区来缓冲结果。我应该重新阅读文档并了解为什么fcntl.ioctl(file.fileno(), 0x80016a11)不起作用。

相关内容

  • 没有找到相关文章

最新更新