Jak dołączyć lokalne pliki nagłówkowe do modułu jądra Linux

17

Powiedzmy, że mam moduł mymodz plikami źródłowymi w następujący sposób:

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

Próbuję dołączyć plik mymod.h w następujący sposób

#include <mymod.h>

Mój plik makefile zawiera, EXTRA_CFLAGS= -I$(shell pwd)/../inc/ale po utworzeniu jądra pojawia się błąd:

Nie znaleziono mymod.h

Wydaje się, że powodem jest to, że kiedy tworzone są moduły jądra, to polecenie jest uruchamiane z makefile: (przy użyciu makeV1):

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

W innych pracach mój $(shell pwd)został rozszerzony do <path/to/linux>. Nie tego chcę. Jak mogę określić -Iparametr, który ma wskazywać na src/incmoje mymoddrzewo źródłowe?

Om Narasimhan
źródło

Odpowiedzi:

19

Pliki makra jądra Linux używają frameworka Kbuild. Chociaż są one interpretowane przez GNU make, Kbuild składa się z dużego zestawu makr o szczególnych konwencjach użytkowania, więc typowe wytyczne makefile nie mają zastosowania. Zaletą Kbuild jest to, że potrzebujesz bardzo małej płyty grzewczej, biorąc pod uwagę złożoność zadania.

Kbuild jest udokumentowany w źródle jądra, w Documentation/kbuild. Jako twórca modułów powinieneś szczególnie czytać modules.txt(i przynajmniej przeglądać inne).

To, co teraz robisz, nie działa, ponieważ $(shell pwd)jest rozszerzane, gdy EXTRA_CFLAGSużywana jest zmienna. Ponieważ plik makefile jest uruchamiany z drzewa źródeł jądra, a nie z katalogu modułu (jest to jeden z wielu nieoczywistych aspektów Kbuilda), wybiera niewłaściwy katalog.

Oficjalny idiom określający dołączanie katalogów do modułu nienależącego do drzewa znajduje się w § 5.3 z modules.txt. srcZmienna jest ustawiona na katalogiem głównym twojego modułu. W związku z tym:

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

Zauważ, że ta deklaracja powinna znajdować się w pliku wywoływanym Kbuildw katalogu głównym drzewa modułów. (Możesz uznać srckatalog za katalog główny drzewa modułów; jeśli tak, umieść Kbuildtam i zastąp powyższą wartość przez -I$(src)/inc). Możliwe jest również umieszczenie ich w Makefile, ale należy pamiętać, że ta definicja (o ile cokolwiek innego, co ma zastosowanie tylko podczas budowania modułu jądra) powinna być objęta dyrektywą warunkową ifeq ($(KERNELRELEASE),). Patrz § 4.1 z modules.txt.

Jeśli nie masz jeszcze Kbuildpliku i chcesz przejść do jego posiadania, przeczytaj §4.1 modules.txt. Posiadanie osobnego Kbuildpliku jest nieco wyraźniejsze. Nie umieszczaj niczego, co dotyczy jądra w głównym pliku makefile, poza regułą do wywołania make -C $(KERNELDIR) M=$(pwd). W Kbuildminimum potrzebna jest lista modułów, które budujesz (często tylko jeden) i lista plików, które chcesz dołączyć do modułu, a także deklaracja zależności:

EXTRA_CFLAGS := -I$(src)/inc
obj-m := mymod.o
mymod-y := $(src)/mod/mymod.o
$(src)/mod/mymod.o: $(src)/inc/mymod.h
Gilles „SO- przestań być zły”
źródło
Nie mogłem zaktualizować posta, ponieważ nie miałem wystarczającej reputacji.
Om Narasimhan,
1
@Om Narasimhan: Jeśli to pomogło ci znaleźć rozwiązanie, powinieneś zaznaczyć odpowiedź jako zaakceptowaną.
CVn
1

Tradycyjnie sposobem na #includepliki ze ścieżkami względem katalogu bieżącego kodu źródłowego jest użycie cudzysłowów zamiast nawiasów kątowych:

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

W tym przypadku pierwszy #includebędzie odwoływał się do ścieżki przeszukiwania kompilatora (która w przypadku gcc jest kontrolowana przez -Iprzełącznik wiersza poleceń), podczas gdy drugi będzie szukał katalogu zawierającego plik źródłowy z #include.

Takie ścieżki też mogą być względne. Więc w src / mod / mymod.c możesz powiedzieć:

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

i powinno „po prostu działać”.

Nie wiem, czy jest to powszechna praktyka w drzewie jądra Linuksa, ale z pewnością jest lepsza niż wygrywanie ścieżki włączania, która może mieć dowolną liczbę niezamierzonych efektów ubocznych.

CVn
źródło
1
Ogólnie dobra rada, jednak pliki makra jądra Linux są bardzo osobliwe. Wzywają dość złożony zestaw makr o nazwie Kbuild; często najlepiej traktować Kbuild jako język, który jest prawie, ale nie całkiem, zupełnie odmienny od marki.
Gilles „SO- przestań być zły”
1
Jasne, ale zachowanie kompilatora C polegającego na szukaniu <foo> w jakimś skonfigurowanym zestawie katalogów oraz na "pasku", patrząc najpierw na bieżący katalog, a następnie wracając do wspomnianej wcześniej ścieżki, nie zmieni się przez to, co dziwnie oznacza, zwane kompilator w pierwszej kolejności.
vonbrand,