C LANGUAGE TECHNOLOGY

【C言語】Linuxのカーネルモジュールで「Hello World!」を表示する方法

悩んでいる人

C言語でLinuxのカーネルモジュールで「Hello World!」を表示する方法を教えて!

こういった悩みにお答えします.

本記事の信頼性

  • リアルタイムシステムの研究歴12年.
  • 東大教員の時に,英語でOSの授業.
  • 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校コンピュータサイエンス学部2021年の世界大学学術ランキングで20位)で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発
  • プログラミング歴15年以上,習得している言語: C/C++Solidity/Vyper,Java,Python,Ruby,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
  • 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」GitHubにオープンソースとして公開

こういった私から学べます.

【C言語】Linuxのカーネルモジュール

Linuxのカーネルモジュールは,Linuxカーネルの機能を動的に追加できる仕組みのことです.

カーネルモジュールを利用すると,カーネルの再コンパイルや再起動せずに実行時にカーネルの機能をロード,アンロードすることができます.

これにより,開発やデバッグの時間を削減することが可能になります.

Linuxのカーネルモジュールは1995年のバージョン1.2で登場しました.

また,Linuxの数多くの機能をモジュールとしてコンパイル可能です.

Linuxカーネルの設定ファイル「.config」で選択することができます.

例えば,.configで「CONFIG_XFS_FS=y」と設定するとカーネルの機能を有効にできますが,以下のように「CONFIG_XFS_FS=m」とするとカーネルモジュールとしてコンパイルできます.

カーネルモジュールとビルトインのカーネルコードの性能差はありません.

カーネルモジュールは,モジュールとしてコンパイルされたバグのあるデバイスドライバを選択的に実行することで特定したい時に有用です.

カーネルモジュールはカーネル全体に対してリンクされます.

カーネルモジュールは,以下で定義されたすべてのLinuxカーネルのグローバルシンボルにアクセスできます.

  • EXPORT_SYMBOL(function or variable name)

名前空間の汚染と変数名の意図しない再利用を避けるために,以下の2つの注意点があります.

  • モジュール名の接頭辞をシンボルにつけること(例:モジュール名がhello_kernel_moduleの場合はhello_kernel_module_func関数)
  • もしシンボルがグローバルの場合,staticをつけること

カーネルのシンボルのリストは/proc/kallsymsにあり,以下のコマンドで表示できます.

また,lsmodコマンドでロードされているモジュールの一覧を確認できます.

カーネルモジュールの解説動画はこちらがわかりやすいです.

カーネルモジュールで「Hello World!」を表示

カーネルモジュールで「Hello World!」を表示する方法を紹介します.

カーネルモジュールのビルド

まず,カーネルモジュールのコード一式をこちらからダウンロードして下さい.

以下のコマンドで解凍した後にディレクトリの内容を表示します.

以下の2つのファイルがあることがわかります.

  • Makefile:カーネルモジュール用の構成ファイル
  • hello_kernel_module.c:カーネルモジュールのコード

カーネルモジュール用のMakefileは,従来のユーザレベルのコード用のMakefileと書き方が少し異なります.

注意点は以下になります.

  • 現在実行しているLinuxカーネルのソースディレクトリKDIRを指定していること
  • カーネルモジュールのソースコードがカーネルソースから外れていること
  • コンパイル後のカーネルモジュールとして,拡張子が.koのファイルが作成されること(このMakefileではhello_kernel_module.koを作成)

hello_kernel_module.cは以下になります.

hello_kernel_module_init関数は,「__init」で定義し,module_initマクロで初期化時のエントリポイントとして設定しているため,カーネルモジュールのロード時に実行します.

hello_kernel_module_exit関数は,「__exit」で定義し,module_exitマクロで終了時のエントリポイントとして設定しているため,カーネルモジュールのアンロード時に実行します.

参考までに,module_init/module_exitマクロはlinux/include/linux/module.hにあります.

makeでビルドします.

カーネルモジュールの実行

カーネルモジュールの実行方法を紹介します.

カーネルモジュールは,rootでないとロードやアンロードできない(実行できない)ことに注意して下さい.

また,カーネルモジュールは特定のカーネルバージョンに対してコンパイルされ,他のカーネルではロードできないことに注意してください.

※このチェックはmodversionsと呼ばれる機構により回避することができますが,危険な場合があります.

insmodコマンドでカーネルモジュールhello_kernel_module.koをロードします.

カーネルモジュールがロードされて「__init」があるhello_kernel_module_init関数が実行します.

dmesgコマンドで確認すると「Hello World!」が表示されていることがわかります.

lsmodコマンドを実行するとhello_kernel_moduleがあることがわかります.

また,modinfoコマンドでhello_kernel_module.koの情報を取得できます.

カーネルモジュールを削除するにはrmmodコマンドを利用します.

カーネルモジュールがアンロードされて「__exit」があるhello_kernel_module_exit関数が実行します.

dmesgコマンドで確認すると「Goodbye World!」が表示されていることがわかります.

まとめ

C言語でLinuxのカーネルモジュールで「Hello World!」を表示する方法を紹介しました.

カーネルモジュールを作成して,カーネルレベルのプログラミングを習得しましょう!

カーネルモジュールを深く理解したいあなたは,以下を読みましょう!

Linuxカーネルのデバッグ方法を知りたいあなたはこちらからどうぞ.

C言語 Linuxカーネル デバッグ
【C言語】Linuxカーネルのデバッグ方法【printk,BUG_ON,WARN_ON,QEMU,GDB】

こういった悩みにお答えします. こういった私から学べます. 本記事は以下の記事を理解していることを前提とします. 目次1 【C言語】Linuxカーネルのデバッグ方法2 printk関数2.1 prin ...

続きを見る

C言語を独学で習得することは難しいです.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!

友だち追加

独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

-C LANGUAGE, TECHNOLOGY
-, , ,