Зачем приложениям пользовательского пространства нужны заголовки ядра?

10

Я собираю busy-box и iptables для встроенного устройства, и одной из зависимостей для них являются заголовки ядра.

Я искал во всей файловой системе файлы * .ko и не нашел ни одного. Итак, я пришел к выводу, что приложения не создают никаких загружаемых драйверов (модулей ядра).

В каких других случаях приложению пользовательского пространства требуются заголовки ядра?

TheMeaningfulEngineer
источник
Простой пример, который можно привести, - когда что-то в пространстве пользователя вызывает системный вызов.
Сами Лэйн
@SamiLaine Я бы предположил, что библиотека c предоставит интерфейс для системных вызовов. Если бы то, что вы говорите, имело место, разве вам не пришлось бы, например, импортировать заголовки ядра просто для того, чтобы открыть сокет?
TheMeaningfulEngineer
Socket (2), это системный вызов, а не библиотечная функция, так что да.
Сами Лэйн
@SamiLaine Можете ли вы привести пример, где вы должны include <linux/*.h>открыть сокет? (Я стремился к sys / socket.h)
TheMeaningfulEngineer

Ответы:

8

Потому что эти программы созданы для использования вещей, определенных в заголовках ядра:

busybox-1.22.1]$ egrep -RHn '^#include <linux'
modutils/modutils-24.c:194:#include <linux/elf-em.h>
include/fix_u32.h:17:#include <linux/types.h>
libbb/loop.c:11:#include <linux/version.h>
console-tools/openvt.c:23:#include <linux/vt.h>
console-tools/kbd_mode.c:23:#include <linux/kd.h>
console-tools/showkey.c:19:#include <linux/kd.h>
util-linux/blockdev.c:36:#include <linux/fs.h>
util-linux/mkfs_ext2.c:50:#include <linux/fs.h>
util-linux/mkfs_vfat.c:28:#include <linux/hdreg.h> /* HDIO_GETGEO */
util-linux/mkfs_vfat.c:29:#include <linux/fd.h>    /* FDGETPRM */
....

Для каждого конкретного инструмента вам нужно прочитать исходный код инструмента и соответствующий заголовок ядра, чтобы выяснить, что именно.

Вы можете увидеть несколько вещей, которые прокомментированы, чтобы сделать это легко.

Например, mkfs_vfatвключает linux/fd.hв себя получить FDGETPRM:

$ egrep -RHn FDGETPRM util-linux/mkfs_vfat.c
util-linux/mkfs_vfat.c:29:#include <linux/fd.h>    /* FDGETPRM */
util-linux/mkfs_vfat.c:351:         int not_floppy = ioctl(dev, FDGETPRM, &param);

Вы, вероятно, могли бы удалить релевантные данные #includeи следить за ошибками компилятора, чтобы упростить их; вы получите предупреждения о том, что некоторые вещи не определены. Эти вещи, вероятно, происходят из заголовков ядра.

suprjami
источник
2
1. Busybox разработан для встроенных и других легких систем, где вы хотите загрузить как можно меньше библиотек в память. Я не читал источник, но, вероятно, BB в основном обходит библиотеки и напрямую ссылается на ядро. 2. Нет. Он связывает ваш бинарный файл в пользовательском пространстве с версией API ядра , которая обратно совместима: бинарный файл, скомпилированный сегодня, может не работать на более старом ядре (в зависимости от включенных символов ... прочтите исходный код), но работать с будущими ядрами.
Игнис
1
@suprjami ABI подчиняется стандарту SysV ABI, который, как можно разумно предположить, не изменяется; помимо прочего, SysV ABI - это то, почему вы можете связать ядро ​​с вашим компилятором (и версией) по своему выбору, не обязательно того самого, который испустил двоичный файл ядра.
Игнис
1
... это также позволяет использовать chroot / LXC в дистрибутиве с другим ядром. и т. д.
ignis
1
(Для ясности: обратите внимание, что ядро ​​имеет внешний ABI , о котором мы здесь говорим, и внутренний ABI между модулями ядра, который претерпевает частые и, возможно, несовместимые изменения, но он не виден в пространстве пользователя и не имеет значения при компиляции пространства пользователя код.)
ignis
1
(Также обратите внимание, что ABI = / = API. API ядра (внешний) включает символы, на которые есть ссылки в исходном коде, и разработчики ядра взяли на себя обязательство поддерживать совместимость; если символы очень редко используются в программном обеспечении реального мира, это будет необоснованный шаг для них, чтобы сделать несовместимые изменения, хотя ни один сторонний стандарт не предписывает весь API Linux, и поэтому ничто технически не препятствует ему.)
ignis