Как включить локальные заголовочные файлы в модуль ядра Linux

17

Скажем, у меня есть модуль mymodс исходными файлами следующим образом:

src / mod / mymod.c
src / inc / mymod.h

Я пытаюсь включить mymod.h следующим образом

#include <mymod.h>

Мой make-файл содержит, EXTRA_CFLAGS= -I$(shell pwd)/../inc/но когда ядро ​​сделано, я получаю сообщение об ошибке:

mymod.h не найден

Причина, по-видимому, заключается в том, что при создании модулей ядра эта команда запускается из make-файла: (с использованием makeV1):

make -C <path/to/linux/src> M=<path/to/mymod> modules

В других работах мой $(shell pwd)расширился до <path/to/linux>. Это не то, что я хочу. Как я могу указать -Iпараметр для указания src/incмоего mymodдерева исходных текстов?

Ом Нарасимхан
источник

Ответы:

19

Сборочные файлы ядра Linux используют фреймворк Kbuild. Хотя они интерпретируются GNU make, Kbuild состоит из большого набора макросов с особыми соглашениями об использовании, поэтому типичные рекомендации для make-файлов не применяются. Приятной особенностью Kbuild является то, что вам нужно очень мало шаблонов, учитывая сложность задачи.

Kbuild документирован в исходном коде ядра, в Documentation/kbuild. Как писатель модулей, вы должны особенно читать modules.txt(и хотя бы пролистывать остальные).

То, что вы делаете сейчас, не работает, потому что $(shell pwd)раскрывается при использовании EXTRA_CFLAGSпеременной. Поскольку make-файл запускается из дерева исходных текстов ядра, а не из каталога вашего модуля (это один из многих неочевидных аспектов Kbuild), он выбирает неправильный каталог.

Официальная идиома для указания включаемых каталогов в модуле вне дерева - в §5.3 modules.txt. srcПеременная устанавливается в каталог верхнего уровня вашего модуля. Следовательно:

EXTRA_CFLAGS := -I$(src)/src/inc

Обратите внимание, что это объявление должно быть в файле, который вызывается Kbuildв корне дерева вашего модуля. (Возможно, вы захотите считать srcкаталог корнем дерева модулей; если это так, поместите Kbuildего и замените указанное выше значение на -I$(src)/inc). Также возможно поместить их в a Makefile, но имейте в виду, что это определение (при условии, что все остальное, что применяется только при сборке модуля ядра) должно быть в условной директиве ifeq ($(KERNELRELEASE),). Смотрите §4.1 modules.txt.

Если у вас еще нет Kbuildфайла и вы хотите перейти на него, прочитайте §4.1 из modules.txt. Наличие отдельного Kbuildфайла немного понятнее. Не помещайте ничего, что относится к ядру, в ваш основной make-файл, кроме правила вызова make -C $(KERNELDIR) M=$(pwd). В Kbuildдействительности, минимум, который вам нужен, это список создаваемых вами модулей (часто только один) и список файлов, которые нужно включить в ваш модуль, плюс объявление зависимости:

EXTRA_CFLAGS := -I$(src)/inc
obj-m := mymod.o
mymod-y := $(src)/mod/mymod.o
$(src)/mod/mymod.o: $(src)/inc/mymod.h
Жиль "ТАК - прекрати быть злым"
источник
Я не смог обновить пост, потому что мне не хватило репутации.
Ом Нарасимхан
1
@ Om Narasimhan: Если это помогло вам найти решение, отметьте ответ как принятый.
CVn
1

Традиционно путь к #includeфайлам с путями относительно каталога текущего исходного кода заключается в использовании кавычек, а не угловых скобок:

#include <stdio.h>
#include "mygreatfunctions.h"

В этом случае первый #includeбудет ссылаться на путь поиска включения компилятора (который, в случае gcc, управляется -Iпереключателем командной строки), тогда как второй будет искать в каталоге, который содержит исходный файл, с помощью #include.

Такие пути тоже могут быть относительными. Итак, в src / mod / mymod.c вы можете сказать:

#include "../inc/mymod.h"

и это должно "просто работать".

Я не знаю, является ли это обычной практикой в ​​дереве ядра Linux, но, конечно, это лучше, чем копаться в пути включения, который может иметь любое количество непреднамеренных побочных эффектов.

CVn
источник
1
В общем, хороший совет, однако сборочные файлы ядра Linux очень своеобразны. Они вызывают довольно сложный набор макросов под названием Kbuild; часто лучше относиться к Kbuild как к языку, который почти, но не совсем, совсем не похож на make.
Жиль "ТАК - перестань быть злым"
1
Конечно же, но поведение компилятора C при поиске <foo> в некотором сконфигурированном наборе каталогов и для «bar», смотрящего сначала на текущий каталог, а затем возвращающегося к пути, указанному ранее, не изменится с помощью странного средства, называемого компилятор в первую очередь.
vonbrand