カーネルドライバーとカーネルモジュールの違いは何ですか?


67

lspci -k3.2.0-29-genericカーネルを使用してKubuntu を実行すると、次のように表示されます。

01:00.0 VGA compatible controller: NVIDIA Corporation G86 [Quadro NVS 290] (rev a1)
    Subsystem: NVIDIA Corporation Device 0492
    Kernel driver in use: nvidia
    Kernel modules: nvidia_current, nouveau, nvidiafb

カーネルドライバーnvidiaとカーネルモジュールnvidia_currentnouveauありnvidiafbます。

カーネルドライバーとカーネルモジュールの違いは何だろうか?

回答:


78

カーネルモジュールは、with insmodやなど、実行時にカーネルに挿入できるコンパイル済みのコードですmodprobe

ドライバーは、カーネル内で実行されてハードウェアデバイスと通信する少しのコードです。ハードウェアを「駆動」します。コンピューターのほとんどのハードウェアには、関連するドライバーがあります。¹実行中のカーネルの大部分はドライバーコードです。²

ドライバーは、ディスク上のカーネルファイルに静的に組み込まれる場合があります。³ドライバーは、後で動的にロードできるように、カーネルモジュールとして組み込まれる場合もあります。(そして、おそらくアンロードされます。)

標準的な方法は、ドライバーをカーネルに静的にリンクするのではなく、可能であればカーネルモジュールとしてドライバーを構築することです。これにより、柔軟性が向上します。ただし、そうしない正当な理由があります。

  • システムを起動するために、特定のドライバーが絶対に必要な場合があります。initrd機能のため、想像するほど頻繁には起こりません。

  • 静的に構築されたドライバーは、組み込みシステムなど、静的にスコープされたシステムでまさに必要なものです。つまり、どのドライバーが常に必要であり、これが決して変わらないことを正確に事前に知っている場合、動的カーネルモジュールに煩わされない正当な理由があります。

  • カーネルを静的に構築し、Linuxの動的モジュールロード機能を無効にすると、カーネルコードの実行時の変更を防ぎます。これにより、柔軟性が犠牲になりますが、セキュリティと安定性が向上します。

すべてのカーネルモジュールがドライバーではありません。たとえば、Linuxカーネルの比較的最近の機能は、別のプロセススケジューラをロードできることです。別の例として、より複雑なタイプのハードウェアには、低レベルのハードウェアドライバーとユーザーランドの間に位置する複数の汎用レイヤーがあります(USB HIDドライバーなど、USBスタックの特定の要素を実装、基盤となるハードウェアとは無関係です)。


サイド:

  1. この広範なステートメントの1つの例外はCPUチップであり、これには「ドライバー」自体がありません。コンピューターには、ドライバーがないハードウェアも含まれている場合があります。

  2. OSカーネルの残りのコードは、メモリ管理IPCスケジューリングなどの一般的なサービスを提供します。これらのサービスは、先にリンクした例のように、主にユーザーランドアプリケーションを提供するか、ドライバーやその他のイントラが使用する内部サービスである場合がありますカーネルインフラストラクチャ。

  3. ブートプロセスの初期段階でブートローダー/bootによってブート時にRAMにロードされる1つ。


1
モジュールには、ファイルシステム、ネットワークプロトコル、ファイアウォール機能などがあります。一部のハードウェア(WiFiカードなど)はモジュールのスタックを必要とし、一部は一般的なインフラストラクチャを提供し、その他はハードウェア自体を処理します。
フォンブランド

1
これは一般的な概要ですが、OPとまったく同じ質問をした後、この答えに出くわし、「使用中のドライバー」が「モジュール」と異なる理由がまだわかりませんでした。対照的に、@ Jim Parisの答えは正しいです。From man lspci: "-k 各デバイスを処理するカーネルドライバーと、それを処理できるカーネルモジュールを表示します。" あなたはそれを次のように読むことができます:「現在/実際にデバイスを処理しているドライバーと、それを処理できる/意図しているすべてのモジュールを表示する」。
ビナルス

Windowsを知っている場合:モジュールはDLLに非常に似ています。UNIXでは、モジュールは共有オブジェクトに似ていますが、モジュールはカーネル専用です。動的にリンクされたモジュールには、ドライバーを含めることができます。カーネルには、静的にリンクされたドライバーを含めることができます。モジュールはDLL(または.so)とは異なります。これは、カーネルが物事を動的にロードする方法に特定の要件があるためです。
ロボキャット

18

lspci出力に関する特定の質問に答えるために、「カーネルドライバー」行は、現在カードにバインドされているドライバー、この場合は専用nvidiaドライバーを示します。「カーネルモジュール」行には、このカードにバインドできることがわかっているすべてのドライバーが一覧表示されます。ここで、独自のドライバは別の名前を表示します。これは、おそらくlspci、ドライバとそのファイル名と、ドライバ自体にコード化された名前の検出方法によるものです。


ありがとう-それは助けた。私が発行しただけの場合man lspci-それはあなたが書いたものを正確に言います。
ビナルス

5

この素敵なチュートリアルによると:

...モジュールの1つのタイプはデバイスドライバーで、これによりカーネルはシステムに接続されたハードウェアにアクセスできます。

したがって、ツリーを描画しようとすると、モジュールを継承する(拡張する)「デバイスドライバー」があり、より具体的な特性があり、その間に「ハードウェアへのアクセス」があります...


これは部分的に正しいだけです。ドライバは、階層内のクラスのオブジェクトです(はい、Linuxの内部設計は、ほとんどの現在のオペレーティングシステムと同様、オブジェクト指向です)。ただし、ドライバーはモジュール(実行時にロード可能)であるか、カーネルにコンパイルされている可能性があります。コード的には、代替手段に違いはありません(またはほとんどありません)。
vonbrand

4

カーネルモジュールは、デバイスドライバーではない場合があります。

「カーネルドライバー」は明確に定義された用語ではありませんが、試してみましょう。

これは、ハードウェアを駆動しないカーネルモジュールであるため、「デバイスドライバー」と見なすことはできません。

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

MODULE_LICENSE("GPL");

static int myinit(void)
{
    printk(KERN_INFO "hello init\n");
    return 0;
}

static void myexit(void)
{
    printk(KERN_INFO "hello exit\n");
}

module_init(myinit)
module_exit(myexit)

ビルド後、以下で使用できます。

insmod hello.ko

そして、に出力hello initdmesgます。

ただし、デバイスドライバーではないが実際に有用なカーネルモジュールがあります。たとえば、カーネルデバッグ/パフォーマンス情報を公開するモジュールなどです。

通常、デバイスドライバーもカーネルモジュールです。

「デバイスドライバー」であるものの例は、ハードウェアを駆動する必要があり、ハードウェアの説明が複雑になる傾向があるため、生成が少し難しくなります。

ただし、QEMUまたは他のエミュレータを使用して、実際のハードウェアまたは単純化されたハードウェアのソフトウェアモデルを構築できます。これは、ハードウェアとの対話方法を学ぶのに最適な方法です。最小限のPCIデバイスドライバーの簡単な例を次に示します。https : //github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/hello.c

次に、x86で、ハードウェアとの会話が次のようになることがわかります。

「ユーザー空間とカーネル空間の違いは何ですか?」で説明されているように、これらの操作は一般にユーザーランドから実行できませんいくつかの例外は、しかし、があります。https://stackoverflow.com/questions/7986260/linux-interrupt-handling-in-user-space

カーネルは、そのようなハードウェアの相互作用をより簡単で移植性の高いものにするために、より高いレベルのAPIを提供します。

  • request_irq 割り込みを処理する
  • ioreadX およびIOメモリマッピング
  • PCIやUSBなどの一般的なプロトコル向けのさらに高いレベルのインターフェース

0

私の答えはジムに行きます。カーネルドライバーは、ハードウェアを駆動するように設計されたプログラム(カーネルモジュール)です。lspciの出力では、nvidiaはloadedデバイスのモジュールであるため、カーネルドライバーであると表示されます。それに加えて、他の利用可能なカーネルモジュールも利用可能です。

私は、Linuxのコマンドを一覧表示し、ドライバーがある削除することを追加しますlsmodrmmod、それぞれ。これは、モジュールのリストとモジュールの削除を示しています。


0

すべてのドライバーはモジュールです。すべてのモジュールがドライバーではありません。

モジュールは実行時に挿入できます。モジュール/ドライバーは、カーネルとともに静的にコンパイルすることもできます。

典型的なモジュールの初期化には

module_init(init_fn);
init_fn()
{
   /* some code */
}

同じモジュールをドライバーにすることができます

module_init(init_fn);
init_fn()
{
   device_register(&device);
   /* some code */
}

8
ドライバーは常にモジュールではなく、メインカーネルイメージに含めることができます。
ジル「SO-悪であるのをやめる」

3
@Prabagaran:「すべてのドライバーはモジュールです。すべてのモジュールはドライバーではありません。」これは矛盾しています。数学的に言えば、あなたが言っているのはD-> MおよびM->!Dです。これにより、Dおよび!Dが許可されます。
フランチェスコターコ

2
彼は「すべてのドライバーがモジュールである。すべてのモジュールがドライバーではない」ことを意味すると思う。
レナン

4
@Renan:それは正しいでしょうが、この回答の編集履歴を見ると、誰かがすでに間違いを修正しようとしており、著者がそれを元に戻しました。通常、エラーを修正して先に進むために編集しますが、この場合は、間違っているだけで問題を混乱させるため、-1をしました。
カレブ

私が覚えているように(しばらくの間だまされていない)、ロード可能なモジュールとしてビルドできないドライバーがいくつかあります。モジュールとしてしか処理できない他の人を覚えているようです。
フォンブランド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.