python - могут ли номера ioctl отличаться от номеров ioctl C?

Насколько мне известно, номера ioctl хорошо определяются драйверами и регистрируются в ядре.

Я играл с некоторым кодом на питоне для запроса состояний джойстика. Я прочитал этот документ об 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)%x\n", JSIOCGAXES, JSIOCGAXES);
  char number;
  ioctl(fd, JSIOCGAXES, &number);
  printf("Number of axes: %d\n", number);
  close(fd);
  return 0;
}

Вывод программы C:

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

Вывод Python

# 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.

Может быть, проблема связана с преобразованием чисел и типами, понятия не имею ... подсказки?


person Sebastian    schedule 14.07.2012    source источник
comment
Используя fcntl.fcntl(), я получаю эту ошибку: OverflowError: signed integer is greater than maximum. Теперь мне нужно знать, почему C ioctl() правильно управляет аргументом. C ioctl() принимает int в качестве аргумента. Будет ли отслеживание смещения int подходом к определению signed integer в python?   -  person Sebastian    schedule 14.07.2012


Ответы (2)


Все это сводится к тому, что шестнадцатеричные преобразования различны - подключение шестнадцатеричного C дает вам в Python другое число:

>>> 0x80016a11
2147576337

Я не уверен, почему Python и C дают разные шестнадцатеричные значения, но, вероятно, это, по крайней мере, частично связано со знаком - Python '%x' дает шестнадцатеричное значение signed 1, printfs дает неподписанный 2.

Использование шестнадцатеричного значения Python (-7ffe95ef), вероятно, улучшит ситуацию — или, что еще лучше, используйте переменную, как в C, и избегайте ошибок преобразования:

op = _IOR(ord('j'), 0x11, 'c')
...
fcntl.ioctl(file, op)
person lvc    schedule 14.07.2012
comment
Насчет разных шестнадцатеричных значений: думаю, вы правы. Я тестировал с некоторым кодом C. В том, что касается моей проблемы, мне не повезло. Кажется, есть ошибка с 64-битными машинами, но пока она должна быть устранена. Во всяком случае, предложенное решение проблемы тоже не сработало. - person Sebastian; 14.07.2012
comment
У этой ошибки более новая дата. Хотя, похоже, это не работает для меня. - person Sebastian; 14.07.2012

Я собираюсь ответить на свой вопрос.

По какой-то причине единственным способом получить значение с помощью ioctl() из python было выдать этот код:

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

То есть использование буфера для сохранения результата. Я должен перечитать документацию и понять, почему fcntl.ioctl(file.fileno(), 0x80016a11) не работает.

person Sebastian    schedule 14.07.2012
comment
Я могу быть здесь абсолютно неправ, но я думаю, что это может быть потому, что базовый системный вызов ioctl ничего не возвращает, вместо этого он изменяет специальную структуру (struct ifconf из net/if.h?), которую вы передаете. Так что, вероятно, python при использовании базового вызова ioctl должен делать то же самое. - person ffledgling; 31.12.2012