web-dev-qa-db-ja.com

Linuxカーネルモジュールのコンパイル方法:printkが見つかりませんか?

だから、Ubuntu 18.04、カーネル4-15.32ジェネリックで単純なカーネルモジュールをコンパイルしようとしています。

#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void){ 
    printk("<1> Hello,World\n");
    return 0;
}

void cleanup_module(void){
    printk("<1> Goodbye.\n");
}

私は<linux/kernel.h>を持っていることに注意してください。これは、フォーラムで、エラーが発生したときに頻繁に省略されるという参照があるためですが、この場合、その問題はありません。これをgcc -o hello.o hello.cでコンパイルすると、implicit declaration of function 'printk'エラーが発生します。

だから質問は、この最も基本的なカーネルモジュールをどのように正確にコンパイルするのですか?

1

問題をいくつかの教訓で解決しました:

  • 「コンパイル対象のカーネルのカーネルヘッダーを使用する必要があります。デフォルトの/usr/include/linuxを使用しても機能しません」( source

  • gccで直接コンパイルすることは推奨されません-カーネルには kbuild system : "外部モジュールの作成者は、ほとんどの複雑さを隠すメイクファイルを提供する必要があるため、入力するだけです" make」を実行してモジュールを構築します。

  • 何らかの理由で$(PWM)は機能しませんが、$(Shell pwm)は機能します。 (見つかった ここ )。 M=$(PWM)が与えるので、これも役割を果たしました

    make[2]: *** No rule to make target 'Arch/x86/entry/syscalls/syscall_32.tbl', needed by 'Arch/x86/include/generated/asm/syscalls_32.h'.  Stop.
    

    エラー。また、 カーネルのドキュメント ごとに

    
    make -C /lib/modules/`uname -r`/build M=$PWD 
    

    しかし、それを試していません。


私が使用したMakefile:

obj-m += hello.o

KDIR := /lib/modules/$(Shell uname -r)/build

all:
    $(MAKE) -C $(KDIR) M=$(Shell pwd) modules

clean:
    make -C /lib/modules/$(Shell uname -r)/build M=$(Shell pwd) modules

結果のモジュールは期待どおりに機能し、dmesgに印刷されるNiceメッセージ「<1> Hello World」および「<1> Goodbye」で挿入および削除できます。

2