Что возвращать из обработчика IOCTL в user-space если данный IOCTL не поддерживается? В нашем драйвере активно использовался ENOIOCTLCMD. Проблема в том, что он объявлен в linux/errno.h в заголовке которого написано (вольный перевод):
не использовать в пользовательском коде
В данном случае, под пользовательским кодом стоит понимать всё, что не собирается в дереве ядра. Кто-то может не согласить со мной в этом аспекте, но по соображениям переносимости - лучше этому следовать.
Кроме того:
этого кода нет в пользовательских errno.h/cerrno;
для этого когда strerror() вернёт что-то вроде: Unknown error 515 (номер может и отличаться);
константы для этого кода ошибки нет на других платформах (Windows, MacOSX, FreeBSD).
Что использовать-то? А использовать не совсем очевидный: ENOTTY.
Изначально, да и согласно комментариям в include/uapi/asm-generic/errno-base.h:
Not a typewriter
При этом утилита пользовательского пространства errno из комплекта
moreutils говорит:
ENOTTY 25 Inappropriate ioctl for device
Дополнительными аргументами:
интернеты тоже подсказывают такую трактовку;
в ядре Linux оно используется по такому же назначению.
В чём же отличие? Нашёл отличное объяснение в
block/ioctl.c:
* Is it an unrecognized ioctl? The correct returns are either
* ENOTTY (final) or ENOIOCTLCMD ("I don't know this one, try a
* fallback"). ENOIOCTLCMD gets turned into ENOTTY by the ioctl
* code before returning.
Не буду переводить, просто поясню: ENOIOCTLCMD используется во внутренних реализациях, когда есть предположение, что обработку можно выполнить в каком-то стандартном русле, выполнить т.н. fallback. В пользовательское пространство должен вернуться ENOTTY. Точка.
Буквально вчера столкнулся с таким вот поведением QtC:
С учётом того, что я собираю QtC из исходников master-ветки репозитория, первая мысль была: что-то поломали, нужно по быстрому разобраться и откатить. Но всё оказалось чуточку интереснее. Кому интересно - добро пожаловать под кат.
Для Windows драйвер писать в QtC никто в здравом уме и трезвой памяти не будет. Поэтому речь дальше по процессу разработки драйвера для Linux. Я не буду касаться вопросов использования отладчика (KGDB), в основном посмотрим на вопросы запуска модуля ядра на удалённой системе.
В современном мире рекомендуется не использовать include_directories() и target_include_directories(), а экспортировать таргет в стиле пространства имён: Target::Target, например так:
Используем как и раньше include_directories(), но лучше не надо;
Не используем Object Library, что не всегда удобно.
Вопрос, а как можно из командной строки, установить DMG или tar.gz пакет CMake с cmake.org? Второй это просто тарбол, с определённой структурой, можно ли просто распаковать и установить PATH, указывающий на bin директорию внутри?
В голове уложилось пункта 3 от силы. Особенно доставляют пункты, где разные компиляторы ведут себя по-разному. Судя по всему у разработчиков тоже не всё укладывается в голове.
Заметка - часть полёта мысли по написанию кода для MicroBlaze в среде Qt Creator и, возможно, Clion.
Сразу, чем не подошёл родной GDB - в нём нет поддержки Python. Для QtC это критично, поэтому нужно пересобрать, но с поддержкой оного.
Рецепт сборки ниже. Без подробностей, но там всё и так ясно.
Для начала необходимые зависимости. Их не нужно качать отдельно - всё находится в пакете исходников binutils. Порядок отстройки важен. Установку (make install) делать не нужно.
# bfd:./configure --enable-targets=all && make -j8
# opcodes:./configure --enable-targets=all && make -j8
# libiberty:./configure && make -j8
# note: gdb-11.2+, иначе sim не соберётся# gnulibchmod +x ./configure && ./configure && make -j8
# sim:./configure --target=microblaze-xilinx-elf && make -j8
# libdecnumber:./configure && make -j8
Там где указан --target - это важно. Там где указано --enable-targets=all, вместо all можно указать нужный для MicroBlaze. Но я не вдавался в подробности, тем более, что собирается достаточно быстро. Если не указывать ничего - потом будут проблемы на линковке. А если ещё намешать, сначала собрать opcodes, потом bfd с разным набором целей, то ещё и в рантайме будет эпичный креш ;-)
Ну и собираем сам GDB:
./configure --host=x86_64-pc-linux-gnu --target=microblaze-xilinx-elf --prefix=${HOME}/bin/mb-gdb-python --disable-gdbserver --with-python=/usr/bin/python3 --with-system-readline --with-system-zlib
make -j8
make install
Устанавливаю в домашний каталог пользователя. Если нужно в системный - лучше опакетить или ставить в /opt/. Python можно, теоретически, указать и третий. Потом проверю.
UPD: На момент “Февраль 2022” нужно указывать Python 3.
При сборке у себя, проверьте, что использовать в качестве аргумента --host=. Для этого достаточно посмотреть, какой префикс у вашего системного компилятора:
$ gcc -dumpmachine
x86_64-pc-linux-gnu
значит хост - x86_64-pc-linux-gnu.
Кстати,
gdbproxy оказывается не совсем дружит с новыми GDB. Судя по всему причина схожая с
этим. Пока вылечил при помощи небольшого хака. Кроме того, эмпирически выяснил, что, похоже, для thread-id используется int32_t, т.е. знаковый 32-битный тип. Просто сейчас базовые адреса оказались за пределами первой половины 32 битного пространства и, внезапно, появились знаки минуса в ID потоков =-)
AV.io 4K - уже новое железо и новые подходы, теперь запускаемся практически мгновенно
KVM2USB 3.0 - глубокое переосмысление
AV.io HD. По сути, благодаря заложенному потенциалу для модернизации в базовую модель, практически без модификации железа, чисто софтом смогли сделать новый продукт.
Там был задействован
Cypress FX3, а
SDK был построен поверх ThreadX. В качестве JTAG отладчика можно использовать Olimex ARM-USB-OCD-H в связке с
OpenOCD. К сожалению, OpenOCD ничего не знает про треды в RTOS и, хотя, базовая поддержка присутствует в коде, конкретно для нашего процессора использовалась схема стекинга регистров, которая отличалась от того, что было уже реализовано. Пришлось
разбираться и дорабатывать. Профиты от использования JTAG для разработки трудно переоценить, как минимум в случае
распределённой работы.
Итак, время идёт. Теперь очередь за FPGA от Xilinx и его софтовым процессором MicroBlaze, где можно запустить портированый FreeRTOS версии 10.x. Но проблема ровно такая же: поддержки тредов в отладчике нет!