Cómo incluir archivos de encabezado local en el módulo del kernel de Linux

17

Digamos que tengo un módulo mymodcon archivos fuente de la siguiente manera:

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

Intento incluir mymod.h de la siguiente manera

#include <mymod.h>

Mi archivo MAKE contiene EXTRA_CFLAGS= -I$(shell pwd)/../inc/pero cuando se hace el núcleo, aparece un error que dice:

mymod.h no encontrado

La razón parece ser que cuando se hacen los módulos del núcleo, este comando se ejecuta desde el archivo MAKE: (usando makeV1):

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

En otros trabajos me $(shell pwd)expandí a <path/to/linux>. Esto no es lo que quiero. ¿Cómo puedo especificar el -Iparámetro al que señalar src/incmi mymodárbol de origen?

Om Narasimhan
fuente

Respuestas:

19

Los archivos make del kernel de Linux usan el framework Kbuild. Aunque estos son interpretados por GNU make, Kbuild consta de un gran conjunto de macros con convenciones de uso peculiares, por lo que no se aplican las pautas típicas de makefile. Lo bueno de Kbuild es que necesita muy pocas repeticiones teniendo en cuenta la complejidad de la tarea.

Kbuild está documentado en la fuente del núcleo, en Documentation/kbuild. Como escritor de módulos, debe leer especialmente modules.txt(y al menos leer los otros).

Lo que está haciendo ahora no funciona porque $(shell pwd)se expande cuando EXTRA_CFLAGSse usa la variable. Dado que el archivo MAKE se ejecuta desde el árbol fuente del núcleo en lugar del directorio de su módulo (este es uno de los muchos aspectos no obvios de Kbuild), está recogiendo el directorio incorrecto.

El idioma oficial para especificar directorios de inclusión en un módulo fuera del árbol está en §5.3 de modules.txt. La srcvariable se establece en el directorio de nivel superior de su módulo. Por lo tanto:

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

Tenga en cuenta que esta declaración debe estar en un archivo llamado Kbuilden la raíz de su árbol de módulos. (Es posible que desee considerar el srcdirectorio como la raíz de su árbol de módulos; si es así, colóquelo Kbuildallí y reemplace el valor anterior por -I$(src)/inc). También es posible ponerlos en un Makefile, pero tenga en cuenta que esta definición (siempre que cualquier otra cosa que se aplique solo al construir un módulo de kernel) debe estar dentro de una directiva condicional ifeq ($(KERNELRELEASE),). Ver §4.1 de modules.txt.

Si aún no tiene un Kbuildarchivo y desea cambiar a uno, lea §4.1 de modules.txt. Tener un Kbuildarchivo separado es un poco más claro. No ponga nada que se aplique al kernel en su archivo MAKE principal, aparte de una regla para llamar make -C $(KERNELDIR) M=$(pwd). En Kbuild, lo mínimo que necesita es la lista de módulos que está creando (a menudo solo uno) y una lista de archivos para incluir en su módulo, más una declaración de dependencia:

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- deja de ser malvado'
fuente
No pude actualizar la publicación porque no tenía suficiente reputación.
Om Narasimhan
1
@ Om Narasimhan: Si esto te ayudó a encontrar la solución, debes marcar la respuesta como aceptada.
un CVn
1

Tradicionalmente, la forma de #includearchivos con rutas relativas al directorio del código fuente actual es utilizar comillas en lugar de corchetes angulares:

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

En este caso, el primero #includehará referencia a la ruta de búsqueda de inclusión del compilador (que, en el caso de gcc, está controlada por el -Iinterruptor de línea de comando), mientras que el segundo buscará en el directorio que contiene el archivo fuente con el #include.

Tales caminos también pueden ser relativos. Entonces, en src / mod / mymod.c, puedes decir:

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

y debería "simplemente funcionar".

No sé si esta es una práctica común en el árbol del kernel de Linux, pero seguramente es mejor que jugar con la ruta de inclusión, que podría tener cualquier cantidad de efectos secundarios no deseados.

un CVn
fuente
1
Un buen consejo en general, sin embargo, los makefiles del kernel de Linux son muy peculiares. Invocan un conjunto bastante complejo de macros llamado Kbuild; A menudo es mejor tratar Kbuild como un lenguaje que es casi, pero no del todo, completamente diferente al make.
Gilles 'SO- deja de ser malvado'
1
Efectivamente, pero el comportamiento del compilador de C de buscar <foo> en algún conjunto configurado de directorios, y de "barra" mirando primero el directorio actual y luego volviendo a la ruta mencionada anteriormente no cambiará por lo extraño que se llama El compilador en primer lugar.
vonbrand