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?
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:
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 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.
Tradicionalmente, la forma de
#include
archivos con rutas relativas al directorio del código fuente actual es utilizar comillas en lugar de corchetes angulares:En este caso, el primero
#include
hará referencia a la ruta de búsqueda de inclusión del compilador (que, en el caso de gcc, está controlada por el-I
interruptor 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:
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.
fuente