Como incluir arquivos de cabeçalho local no módulo do kernel do linux

17

Digamos que eu tenha um módulo mymodcom arquivos de origem da seguinte maneira:

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

Eu tento incluir mymod.h da seguinte maneira

#include <mymod.h>

Meu makefile contém EXTRA_CFLAGS= -I$(shell pwd)/../inc/mas quando o kernel é criado, recebo um erro informando:

mymod.h não encontrado

A razão parece ser que, quando os módulos do kernel são criados, esse comando é executado a partir do makefile: (usando makeV1):

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

Em outros trabalhos, $(shell pwd)fui expandido para <path/to/linux>. Não é isso que eu quero. Como posso especificar o -Iparâmetro para apontar para a src/incminha mymodárvore de origem?

Om Narasimhan
fonte

Respostas:

19

Os makefiles do kernel Linux usam a estrutura Kbuild. Embora estes sejam interpretados pelo GNU make, o Kbuild consiste em um grande conjunto de macros com convenções de uso peculiares, portanto as diretrizes típicas do makefile não se aplicam. O bom do Kbuild é que você precisa de muito pouco clichê, considerando a complexidade da tarefa.

O Kbuild está documentado na fonte do kernel, em Documentation/kbuild. Como criador de módulos, você deve ler especialmente modules.txt(e pelo menos examinar os outros).

O que você está fazendo agora não está funcionando porque $(shell pwd)é expandido quando a EXTRA_CFLAGSvariável é usada. Como o makefile é executado a partir da árvore de fontes do kernel, e não do diretório do módulo (este é um dos muitos aspectos não óbvios do Kbuild), ele está escolhendo o diretório errado.

O idioma oficial para especificar diretórios de inclusão em um módulo fora da árvore está em §5.3 de modules.txt. A srcvariável é configurada para o diretório de nível superior do seu módulo. Portanto:

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

Observe que esta declaração deve estar em um arquivo chamado Kbuildna raiz da sua árvore de módulos. (Você pode considerar o srcdiretório como a raiz da sua árvore de módulos; nesse caso, coloque Kbuild-o e substitua o valor acima por -I$(src)/inc). Também é possível colocá-los em a Makefile, mas lembre-se de que essa definição (desde que qualquer outra coisa que se aplique apenas ao criar um módulo do kernel) deve estar dentro de uma diretiva condicional ifeq ($(KERNELRELEASE),). Veja §4.1 de modules.txt.

Se você ainda não possui um Kbuildarquivo e deseja mudar para um, leia §4.1 de modules.txt. Ter um Kbuildarquivo separado é um pouco mais claro. Não coloque nada que se aplique ao kernel no seu makefile principal, exceto uma regra a ser chamada make -C $(KERNELDIR) M=$(pwd). Em Kbuild, o mínimo necessário é a lista de módulos que você está construindo (geralmente apenas um) e uma lista de arquivos a serem incluídos no seu módulo, além de uma declaração de dependência:

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- parar de ser mau'
fonte
Não pude atualizar a postagem porque não tinha reputação suficiente.
Om Narasimhan
1
@ Narasimhan: Se isso ajudou você a descobrir a solução, marque a resposta como aceita.
um CVn
1

Tradicionalmente, o caminho para #includearquivos com caminhos relativos ao diretório do código-fonte atual é usar aspas em vez de colchetes angulares:

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

Nesse caso, o primeiro #includefará referência ao caminho de pesquisa de inclusão do compilador (que, no caso do gcc, é controlado pela -Iopção de linha de comando), enquanto o segundo procurará no diretório que contém o arquivo de origem #include.

Esses caminhos também podem ser relativos. Portanto, em src / mod / mymod.c, você pode dizer:

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

e deve "apenas funcionar".

Não sei se isso é prática comum na árvore do kernel do Linux, mas certamente é melhor do que mexer no caminho de inclusão, que pode ter vários efeitos colaterais indesejados.

um CVn
fonte
1
Bons conselhos em geral, porém os makefiles do kernel do Linux são muito peculiares. Eles chamam um conjunto bastante complexo de macros chamado Kbuild; geralmente é melhor tratar o Kbuild como uma linguagem que é quase, mas não completamente, completamente diferente do make.
Gilles 'SO- stop be evil'
1
Com certeza, mas o comportamento do compilador C de procurar <foo> em algum conjunto de diretórios configurado e de "bar" primeiro olhar no diretório atual e depois voltar ao caminho mencionado anteriormente não mudará pelo que significa bizarro chamado o compilador em primeiro lugar.
vonbrand