Cara memasukkan file header lokal dalam modul kernel linux

17

Katakanlah saya memiliki modul mymoddengan file sumber sebagai berikut:

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

Saya mencoba memasukkan mymod.h sebagai berikut

#include <mymod.h>

Makefile saya berisi EXTRA_CFLAGS= -I$(shell pwd)/../inc/tetapi ketika kernel dibuat, saya mendapatkan pesan kesalahan yang menyatakan:

mymod.h tidak ditemukan

Alasannya tampaknya ketika modul kernel dibuat, perintah ini dijalankan dari makefile: (menggunakan makeV1):

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

Di karya lain saya $(shell pwd)diperluas ke <path/to/linux>. Ini bukan yang saya inginkan. Bagaimana saya bisa menentukan -Iparameter untuk menunjuk ke pohon sumber src/incsaya mymod?

Om Narasimhan
sumber

Jawaban:

19

Kernel Linux membuat file menggunakan kerangka kerja Kbuild Meskipun ini ditafsirkan oleh GNU make, Kbuild terdiri dari sejumlah besar macro dengan konvensi penggunaan khusus, jadi pedoman makefile tipikal tidak berlaku. Hal yang menyenangkan tentang Kbuild adalah Anda memerlukan pelat ketel yang sangat sedikit mengingat kompleksitas tugasnya.

Kbuild didokumentasikan dalam sumber kernel, di Documentation/kbuild. Sebagai penulis modul, Anda harus membaca modules.txt(dan setidaknya membaca yang lainnya).

Apa yang Anda lakukan sekarang tidak berfungsi karena $(shell pwd)diperluas ketika EXTRA_CFLAGSvariabel digunakan. Karena makefile berjalan dari pohon kode sumber bukan dari direktori modul Anda (ini adalah salah satu dari banyak aspek non-jelas Kbuild), itu mengambil direktori yang salah.

Ungkapan resmi untuk menentukan menyertakan direktori dalam modul out-of-tree adalah dalam §5.3 dari modules.txt. The srcvariabel diatur untuk direktori level atas modul Anda. Karena itu:

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

Perhatikan bahwa deklarasi ini harus dalam file yang disebut Kbuilddi root pohon modul Anda. (Anda mungkin ingin menganggap srcdirektori sebagai root dari pohon modul Anda; jika demikian, letakkan di Kbuildsana dan ganti nilai di atas dengan -I$(src)/inc). Dimungkinkan juga untuk meletakkannya di dalam Makefile, tetapi perlu diingat bahwa definisi ini (selama hal lain yang hanya berlaku ketika membangun modul kernel) harus berada dalam arahan kondisional ifeq ($(KERNELRELEASE),). Lihat §4.1 dari modules.txt.

Jika Anda belum memiliki Kbuildfile dan ingin beralih untuk memilikinya, baca §4.1 dari modules.txt. Memiliki Kbuildfile terpisah sedikit lebih jelas. Jangan menaruh apa pun yang berlaku untuk kernel di makefile utama Anda, selain aturan untuk memanggil make -C $(KERNELDIR) M=$(pwd). Dalam Kbuild, minimum yang Anda butuhkan adalah daftar modul yang Anda bangun (seringkali hanya satu) dan daftar file untuk dimasukkan dalam modul Anda, ditambah deklarasi dependensi:

EXTRA_CFLAGS := -I$(src)/inc
obj-m := mymod.o
mymod-y := $(src)/mod/mymod.o
$(src)/mod/mymod.o: $(src)/inc/mymod.h
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Saya tidak dapat memperbarui pos karena saya tidak memiliki reputasi yang cukup.
Om Narasimhan
1
@Om Narasimhan: Jika ini membantu Anda mencari solusinya, Anda harus menandai jawabannya sebagai diterima.
CVn
1

Secara tradisional cara untuk #includefile dengan path relatif ke direktori kode sumber saat ini adalah dengan menggunakan tanda kutip daripada kurung sudut:

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

Dalam kasus ini, yang pertama #includeakan merujuk kompilator termasuk jalur pencarian (yang, dalam kasus gcc, dikendalikan oleh -Isaklar baris perintah), sedangkan yang kedua akan mencari di direktori yang berisi file sumber dengan #include.

Jalan seperti itu bisa relatif juga. Jadi di src / mod / mymod.c, Anda dapat mengatakan:

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

dan itu harus "hanya bekerja".

Saya tidak tahu apakah ini adalah praktik umum di pohon kernel Linux, tapi tentu saja ini lebih baik daripada menyiasati dengan menyertakan path, yang dapat memiliki sejumlah efek samping yang tidak diinginkan.

sebuah CVn
sumber
1
Nasihat yang bagus secara umum, namun Linux membuat kernel sangat aneh. Mereka memanggil makro yang cukup kompleks yang disebut Kbuild; sering kali lebih baik memperlakukan Kbuild sebagai bahasa yang hampir, tetapi tidak sepenuhnya, tidak sama dengan membuat.
Gilles 'SO- stop being evil'
1
Benar saja, tetapi perilaku kompiler C mencari <foo> di beberapa set direktori yang dikonfigurasi, dan untuk "bar" mencari pertama di direktori saat ini dan kemudian kembali ke jalan yang disebutkan sebelumnya tidak akan berubah dengan apa yang disebut cara aneh yang disebut kompiler di tempat pertama.
vonbrand