не проходит вызов ioctl();

Вопросы программного кода и архитектуры Linux

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: не проходит вызов ioctl();

Непрочитанное сообщение Olej » 01 ноя 2013, 16:29

just_a_student писал(а):Проблема решена, заменой .compat_ioctl на .unlocked_ioctl:
Как разрешилась проблема (ответьте):
- операция .compat_ioctl начала вызываться?
- .compat_ioctl вызывается и выполняется нормально (дешифрирует код ioctl и т.д. по коду)?

Как?

just_a_student
Писатель
Сообщения: 20
Зарегистрирован: 11 июл 2013, 20:57
Контактная информация:

Re: не проходит вызов ioctl();

Непрочитанное сообщение just_a_student » 01 ноя 2013, 16:52

Olej писал(а):Как разрешилась проблема (ответьте):
- операция .compat_ioctl начала вызываться?
- .compat_ioctl вызывается и выполняется нормально (дешифрирует код ioctl и т.д. по коду)?
compat_ioctl теперь нет вообще. Структура file_operations теперь имеет вид:

Код: Выделить всё

static struct file_operations fops = {
	.owner        = THIS_MODULE,
	.open         = Open,
	.release      = Close,
	.unlocked_ioctl = Ioctl,
	.mmap         = Mmap,
};
Вызов из тестовой программы я не менял. Теперь вызов ioctl из тестовой программы успешно перенаправляется на функцию Ioctl() из модуля.
Olej писал(а):Теперь, в дополнение к версиям ядра, вы ещё разберитесь: какая у вас система - 32 или 64 бит, и с какими библиотеками и как вы компилируете свои приложения (пользовательского пространства).
Тут путаница есть небольшая. Раньше эта тестовая программа и модуль успешно работали на одноплатном компьютере в первоначальном виде (с compat_ioctl). Но это было давно, когда и ядро для одноплатного компьютера и тестовая программа компилировались на 32 битном компьютере. Теперь же ядро я компилировал на 64 битной машине, но с параметрами для 32битного железа, а тестовую программу компилирую на этой же машине но через virtual box, на которой установлена 32 Ubuntu (я не смог компилировать без вирт машины, так как в программе используется библиотека boost::thread, которая не позволяет делать кросс-компиляцию 64x->32x. По крайней мере я не понял как это делать)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: не проходит вызов ioctl();

Непрочитанное сообщение Olej » 01 ноя 2013, 17:43

just_a_student писал(а): Есть драйвер, в котором объявлена структура file_operations:

Код: Выделить всё

static struct file_operations fops = {
	.owner        = THIS_MODULE,
	.open         = Open,
	.release      = Close,
        .compat_ioctl = Ioctl,
	.mmap         = Mmap,
};
Из кода тестовой программы происходит вызов:

Код: Выделить всё

::ioctl(arg1, arg2, arg3);
В порядке примечания:

- вы где-то раньше писали (совсем недавно), что переделываете драйвер, работающий с достаточно старым ядром...
- в котором, соответственно, не могло быть .compat_ioctl ... потому как должен бы быть в этом месте .ioctl

Или это вы дописываете свою новую функциональность к драйверу?

Вот по этому поводу я и добавлю в качестве примечания:
- ioctl() - это очень старый механизм (API) ...
- очень опасный из соображений полного отсутствия контроля типов параметров ...
- и в новых разработках его лучше не использовать,
- а там, где нужна подобная функциональность, использовать отображения управляемых переменных в /proc или /sys.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: не проходит вызов ioctl();

Непрочитанное сообщение Olej » 01 ноя 2013, 18:16

just_a_student писал(а): Вызов из тестовой программы я не менял. Теперь вызов ioctl из тестовой программы успешно перенаправляется на функцию Ioctl() из модуля.
Я не случайно спрашивал: "успешно перенаправляется", или успешно выполняется вызов операции ioctl() (с ожидаемым результатом)???

Потому, что в предшествующих версиях ядра операция (поле .ioctl) определялась в struct file_operations с прототипом:

Код: Выделить всё

        int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
А теперь обработчики для ioctl определяются с прототипом:

Код: Выделить всё

        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
И если в старом коде (использующем .ioctl) только заменить .ioctl в инициализации struct file_operations на .unlocked_ioctl , то происходят очень смешные вещи (я только-что проверил на коде своих примеров!):
- код нормально скомпилируется ... будут только невнятные warning-и на инициализацию struct file_operations и не более!
- модуль будет загружаться ... как-будто ОК!
- но нормально дешифрироваться коды ioctl() не будут - параметры вызова "сдвинуты" ...
- и будет сыпаться ошибка (уже из обработчика ioctl - ... "успешно перенаправляется" ;-) ) о недопустимом коде операции (правда, если там стоит контроль допустимости кода ioctl() ... что люди, знающие об опасности этой операции, делают всегда).

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: не проходит вызов ioctl();

Непрочитанное сообщение Olej » 01 ноя 2013, 18:27

Olej писал(а): Они разнесли вызов ioctl() в 2: unlocked_ioctl() + compat_ioctl() ...
И произошло это (очередное переопределение struct file_operations) между версиями 2.6.33 (http://lxr.linux.no/#linux+v2.6.33/include/linux/fs.h) и 2.6.34 (http://lxr.linux.no/#linux+v2.6.34/include/linux/fs.h).

В 2.6.33 это ещё ioctl(), а в 2.6.34 - это уже unlocked_ioctl() + compat_ioctl().

just_a_student
Писатель
Сообщения: 20
Зарегистрирован: 11 июл 2013, 20:57
Контактная информация:

Re: не проходит вызов ioctl();

Непрочитанное сообщение just_a_student » 01 ноя 2013, 19:58

Olej писал(а):- вы где-то раньше писали (совсем недавно), что переделываете драйвер, работающий с достаточно старым ядром...
- в котором, соответственно, не могло быть .compat_ioctl ... потому как должен бы быть в этом месте .ioctl
Да, но видимо оно не настолько старое как я думал. Мне говорили что этой системе(драйвер + программы) лет пять, но судя по всему ее переделывали при переходе на ядро 2.6.34.
Olej писал(а):В 2.6.33 это ещё ioctl(), а в 2.6.34 - это уже unlocked_ioctl() + compat_ioctl().
Вот и поспевай после этого за разработчиками ядра! :-(
Olej писал(а):- ioctl() - это очень старый механизм (API) ...
- очень опасный из соображений полного отсутствия контроля типов параметров ...
- и в новых разработках его лучше не использовать,
Когда буду переделывать все это добро, которое сейчас запускал, постараюсь этого избежать! Спасибо! :)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: не проходит вызов ioctl();

Непрочитанное сообщение Olej » 01 ноя 2013, 20:25

just_a_student писал(а):
Olej писал(а):- вы где-то раньше писали (совсем недавно), что переделываете драйвер, работающий с достаточно старым ядром...
- в котором, соответственно, не могло быть .compat_ioctl ... потому как должен бы быть в этом месте .ioctl
Да, но видимо оно не настолько старое как я думал. Мне говорили что этой системе(драйвер + программы) лет пять, но судя по всему ее переделывали при переходе на ядро 2.6.34.
2.6.34 - это уровень Fedora 15-16, и год ... где-то начала 2012.

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 6 гостей