LoginSignup
10
8

More than 5 years have passed since last update.

Linux カーネルモジュールのコンパイル

Posted at

Linux カーネルモジュールのコンパイルを行った際に何をやっているか調べてみました。

簡単なカーネルモジュール

  • まず簡単なカーネルモジュールのソースコードとMakefileを用意します。
/*  
 *  hello.c - The simplest kernel module.
 */
#include <linux/module.h>   /* Needed by all modules */
#include <linux/kernel.h>   /* Needed for KERN_INFO */

int init_module(void)
{
    printk(KERN_INFO "Hello world 1.\n");

    /* 
     * A non 0 return means init_module failed; module can't be loaded. 
     */
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye world 1.\n");
}
obj-m = hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

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

makeすると、どんなコマンドが実行されるか

簡単なカーネルモージュルをコンパイルするとどんなコマンドが実行されるのか。

make

をすると、カーネルソースに含まれる3つのmakefileが実行されていました。

make -C /lib/modules/3.13.0-62-generic/build M=/home/eggman/tmp/driver/kernelmodule modules
make -f scripts/Makefile.build obj=/home/eggman/tmp/driver/kernelmodule
make -f /usr/src/linux-headers-3.13.0-62-generic/scripts/Makefile.modpost

Makefile で適用されるルール

  • 引数Mで指定した値をKBUILD_EXTMODに設定。
  • KBUILD_EXTMODからmodule-dirsを設定
  • ターゲット $(module-dirs)を生成後に、ターゲット modules を生成する。
  • $(build) がどう設定されるかわかりませんが、 -f scripts/Makefile.build obj が設定されてました。
ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif

module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
PHONY += $(module-dirs) modules
$(module-dirs): crmodverdir $(objtree)/Module.symvers
        $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)

modules: $(module-dirs)
        @$(kecho) '  Building modules, stage 2. ';
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost

scripts/Makefile.build で適用されるルール

  • けっこう複雑でした。

  • .cを.oを変換するのは このルールです。

$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
  • if_changed_ruleはscript/Kbuild.includeで定義されています。
if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ),                 \
        @set -e;                                                             \
        $(rule_$(1)))
  • これは rule_cc_o_c を行います。
define rule_cc_o_c
        $(call echo-cmd,checksrc) $(cmd_checksrc)                         \
        $(call echo-cmd,cc_o_c) $(cmd_cc_o_c);                            \
        $(cmd_modversions)                                                \
        $(call echo-cmd,record_mcount)                                    \
        $(cmd_record_mcount)                                              \
        scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' >    \
                                                      $(dot-target).tmp;  \
        rm -f $(depfile);                                                 \
        mv -f $(dot-target).tmp $(dot-target).cmd
endef
  • けっきょき cmd_cc_o_c を実行します。
cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<

scripts/Makefile.modpost で適用されるルール

  • .koを生成します。
$(modules): %.ko :%.o %.mod.o FORCE
        $(call if_changed,ld_ko_o)```

リンカで.oを.koに変換します。

      cmd_ld_ko_o = $(LD) -r $(LDFLAGS)                                 \
                             $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
                             -o $@ $(filter-out FORCE,$^)

参考にしたページ

ずっと下書きにあったけど、公開しとく。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8