します。https://blog.csdn.net/weixin_42462202/article/details/99887783からコピー
Linuxドライバのエントリの()キャラクタデバイスドライバの基礎
記事のディレクトリ
Linuxドライバのエントリ()デバイスドライバの基本文字
ドライブはじめ
IIキャラクタデバイスドライバの概念
第三に、登録したキャラクタデバイス
4またはモジュールをコンパイル
5つのロードモジュール
第六は、デバイスノードを作成します
7テスト
ドライブはじめ
キャラクタデバイスドライバへのLinuxドライバ、ブロックデバイスドライバ、ネットワークデバイスドライバ
キャラクタデバイスドライバ
アクセスのシリアル順にデバイスの必須の文字、などが主導し、タッチスクリーン、マウスなど
オープン、クローズ、読み取り、書き込み、および他のシステムを介してアクセスコール
ブロックデバイスドライバ
ブロックアクセスデバイスは、ハードディスクとして動作するようにブロック単位で、任意の順序であってもよく、そうEMMC
そこ設計ブロックおよびキャラクタデバイスをドライブ大きな違いがありますが、またオープン、クローズ、読み取り、書き込み、および他のシステムコールを介してアクセスすることができますが、これらは一般的に管理するには、ファイル・システムを使用しています
ネットワークデバイスドライバ
ネットワークデバイスは、ファイルシステムでは、データパケットを受信及び送信するために設計されており、該当するデバイスノードが存在しない、ソケットインタフェースを介してアクセスされます
主に文字のデバイス上のこの論文
第二に、キャラクタデバイスドライバの概念
オープン、読み取り、書き込み、および他のシステムコールを通じてデバイスノードは/ dev /率い、アプリケーション層は、制御を導くことができるよう、Linuxのすべての下では、このようなファイルシステムでつながったデバイスの性能として、ファイルであります
例えば、LEDライトが欲しい、デバイスファイルの書き込みを開く1
int型fdが。
int型のval = 1;
オープン= FD( "は/ dev / LED"、XXX);
書き込み(FD&ヴァル、はsizeof(ヴァル));
などは、それが導くことができることを点灯します
今、あなたはLEDライトアップをすることができることを、なぜそう質問、考えますか?
LEDライトを取得するには、完成した作品つながったドライブの一部であるハードウェア、オペレーティング・ハードウェアを動作させる必要があります
最も簡単な方法は、オープン操作、led_open LEDドライバの、対応する一つにつながったアプリケーション層のために、です。書き込み操作のために、アプリケーション層、次いでled_write動作は、ハードウェアを制御するドライバled_writeの対応する一つにつながった操作につながっ、次いでLED制御
そして、LEDデバイスは、オープンノード上で、writeシステムコールは、どのようにそれをled_write、ドライバーのled_openに呼び出すには?
アプリケーション層は、オープン、読み取り、書き込み、および他の操作を呼び出すと、システムは、カーネルモードになることを引き起こして、例外が発生し、その後SYS_OPEN対応するシステムコールを実行するために、SYS_READ、SYS_WRITE等
適切なドライバは、SYS_OPEN SYS_READ、SYS_WRITE、その後、動作させるために、ドライバのオープン、読み取り、書き込みハードウェアを呼び出す見つけるに行きます
図に示すように。
仮想ファイルシステムに呼び出してSYS_OPEN、どのように他のドライバーが行う代わりにLEDドライバを見つけましたか?
まず、デバイス番号を教えて
各装置12は、マスタ・デバイスの高い数を示すデバイス番号、32ビットを有し、20は下部マイナー番号を表します
使用lsのは/ dev / LED -l視聴デバイスは、以下の情報を得ることができます
ルート-RW。1 ---- CRW 0 10 1 12:00 131日の/ dev / LED
。1
項10、131表し、デバイス番号、デバイス番号10が示すマスター、マイナー番号131表します
理解を容易にするために、我々は、マスタ・デバイスのインデックス番号にカーネルアレイ装置内の文字があることを考慮することができ、デバイス自体が文字配列要素である、業務のキャラクタデバイスファイルセット、機能(例えばled_openを設定する一連の動作が、そこにありますled_write、led_read)
マスターファイルによって機器の良い配列を見つけるためにSYS_OPENシステムコール、キャラクタデバイスファイル操作や他の機能が率いるドライバーのled_openへの呼び出しのセット
キャラクタデバイスドライバは、FOPS(ファイル操作のセット)を改善して、デバイス番号を指定して、カーネルのキャラクタデバイスまでのことです
第三に、キャラクタデバイスは、登録された
キャラクタデバイスオブジェクトを初めて目に
構造体file_operations {
ssize_tの(*読み取り)(構造体ファイル*、チャー__user *、size_tの、loff_t *)。
int型(*オープン)(構造体のinode *、構造体ファイル*)。
...
};
CDEVをストラクト{
たkobject KOBJをストラクト、
構造体Module1の*所有者; / *表示モジュール* /
constの構造体file_operations * OPS、設定/ *ファイル操作* /
LIST_HEAD一覧ストラクト;
たdev_t DEV; / *デバイス番号* /
unsigned int型のCOUNT;
};
dev_t部材は、下部副デバイス番号のデバイス番号、32ビット、高解像度のマスター装置12、20を画定します
カーネルは、2つの主要なとマイナー番号のマクロ以下の取得します
MAJOR(DEVたdev_t)//メジャー番号
MINOR(DEVたdev_t)//マイナー番号
次のマクロ取得装置番号を使用して
mkdev(int型メジャー、マイナーint型)
各デバイスは、独自の文字に対応するデバイス番号の範囲を持って、ここでデバイス番号を適用する方法を説明します
いいえ応用機器ありません
動的割り当て
この機能は、デバイス番号とデバイス番号が動的メジャー番号を割り当てることができる回数を指定します
/ *
* Devの:デバイス番号への応用が返さ
* baseminor:始まるマイナー番号
*回数:アプリケーションデバイスの数数
* /
int型alloc_chrdev_region(dev_tの* DEV、符号なしbaseminor、符号なしのCOUNT、
CONST文字*名)
静的割り当て
この関数は、メジャーとマイナー番号とデバイス番号の数でなければなりません
/ *
*から:実際にデバイス番号
*回数:デバイス番号の数は、
* /
int型(のdev_tから、符号なしのCOUNT、CONST文字*名)register_chrdev_region
アプリケーションデバイス番号が完了した後、あなたはキャラクタデバイスを登録するには、このデバイス番号を使用することができます
登録キャラクタデバイス
機能と文字関連機器
ボイドcdev_init(* file_operationsを構造体、* CDEVを構造体);
CDEV * cdev_alloc(ボイド)をストラクト、
ボイドcdev_put(CDEV * Pを構造体);
intはcdev_add(符号無し、*のdev_tをCDEVを構造体);
ボイドcdev_del(* CDEVを構造体);
cdev_init :設定ファイル操作file_operationsで使用される文字に関連付けられたFOPS及び装置は、操作機能のシリーズ(例えば、オープン、読み取り、書き込み)が提供されます。
cdev_alloc:キャラクタデバイスオブジェクトを割り当てます
cdev_add:登録キャラクタデバイス
cdev_del:キャラクタデバイスのキャンセル
キャラクタデバイスを登録するステップ
構造体CDEV * cdev_alloc(無効); //割り当てキャラクタデバイス
空cdev_init(構造体CDEV *、構造体file_operations *); //バインドFOPS
int型cdev_add(構造体CDEV *、dev_tの 、符号なし); // 文字とデバイス番号がカーネルに登録されたデバイスへの適用が
、以下は、単純な文字デバイスドライバです
mydev.c
#include <linuxの/ module.h>
の#include <linuxの/ init.h>
の#include <linuxの/ fs.h>
の#include <linuxの/ cdev.h>
の#include <linuxの/ slab.h>
静的のdev_tなdev_id。
静的構造体CDEV * mydev。
ssize_tのmydev_read(構造体ファイル*ファイル、チャー__user *データ、size_tのサイズ、loff_t * LOFF)
{
のprintk( "mydev_read \ n");
0を返します。
}
ssize_tのmydev_write(構造体ファイル*ファイル、CONSTチャー__user *データ、size_tのサイズ、loff_t * LOFF)
{
のprintk( "mydev_write \ n");
0を返します。
}
int型mydev_open(のinode構造* iノード、構造体ファイル*ファイル)
{
のprintk( "mydev_open \ N");
0を返します。
}
/ *文件操作集合* /
静的構造体file_operations mydev_fops = {
.owner = THIS_MODULE、
.read = mydev_read、
.open = mydev_open、
.WRITE = mydev_write、
}。
INTは__init静的(ボイド)mydev_init
{
/ *アプリケーション・デバイス番号* /
alloc_chrdev_region(なdev_id&,. 1 ,. 1、 "そのmydevを");
/ *割り当てキャラクタデバイス* /
そのmydev cdev_alloc =();
/ *文字セットデバイス* /
cdev_init(つまりmydev、&mydev_fops)。
/ *登録のキャラクタデバイス* /
cdev_add(mydev、なdev_id、1);
メジャーとマイナー番号* /に/ *印刷要求
のprintk( ":Dの%;マイナー:主要な%D \ N-"、MAJOR(なdev_id)、MINOR(なdev_id));
0を返します。
}
静的__exit空隙mydev_exit(ボイド)
{
cdev_del(mydev)。
kfree(mydev)。
unregister_chrdev_region(なdev_id、1)。
}
module_init(mydev_init)。
module_exit(mydev_exit)。
MODULE_LICENSE(「GPL」);
第四に、コンパイラのモジュール
ドライバの後に書かれたが、どのように我々は、ドライバをコンパイルするか、2つの方法がありますが、1が一緒にカーネルとドライバにコンパイルされ、1が単独のドライバに書き込まれますモジュール
ここでは第二のプレゼンテーション
モジュールはMakefileを書く必要があるとして、ドライバがコンパイルされています
Makefileは次のように
KERN_DIR = /仕事/ linuxの/カーネル/
すべての:
- C $(KERN_DIR)M = `pwd`はモジュールを作ります
クリーン:
メイク- C $(KERN_DIR)M = `pwd`はモジュールのクリーン
RM -rf modules.order
OBJ-M + = mydev.o
KERN_DIR = /仕事/ linuxの/カーネル / カーネルツリーは表して、カーネルのパスを変更する必要に応じて
mydev.cをコンパイルするOBJ-M + = mydev.oショーファイル
-C $(KERN_DIR)M = PWDモジュールは、モジュールをコンパイルし、カーネルソースツリーへのジャンプを表示します
Makefileとmydev.cはmydev.koドライブモジュールを得ることができ、メイクを行い、まとめ
第五に、ロード・モジュール
駆動モジュールを使用するには、insmodのxxx.koをロードすることができます
使用はlsmodは、現在ロードされているモジュールを表示することができます
あなたはrmmodはxxxにロードされたモジュールを使用してドライバをアンインストールすることができます
実験プラットフォームを生成するためにコピー上記mydev.ko、insmodのmydev.koを実行します
ロードされたモジュールたら、カーネルはmodule_init(mydev_init)指定されたモジュールのエントリ、mydev_init機能を実行します、我々は、デバイス番号を適用し、キャラクタデバイスを登録して、メジャーとマイナーデバイス番号を印刷
あなたは、印刷情報を見ることができます
主要:250;マイナー:1
1は、
メジャー番号250を表し、マイナー番号1(あなたは変更になる場合があります何を参照してください)
モジュールがロードされているこの時点で、我々はキャラクタデバイスが登録されていることを猫の/ proc /デバイスを介して見ることができます
しかし、デバイスノードを生成しませんでした、我々はまだ/ devディレクトリに機器を操作することができない、ここではデバイスノードを作成する方法を説明します
六つは、デバイスノードを作成する
デバイスノードを自動的に作成し、手動で作成されているが、以下に分割されている作成を導入しました。
手動で作成します
250;マイナー:主要なプリントアウトするトップドライバーでは1、我々はデバイスノードを作成するには、この情報を使用することができます
デバイスノードを作成するには、次のコマンドにより、
mknodをデバイス名、デバイスタイプ(文字:C、ブロック:B)メジャー番号デバイス番号から
行います
mknodの/ dev / mydev C 250 1つの
デバイスの発生後に実行ノードの/ dev / mydev
自動的に作成
デバイスドライバは、関連情報/ SYSを作成するudevのMDEVまたはデバイスノードが情報に従って作成されたときに自動的に、MDEVのudevの機構または機構を使用して作成され
以下は、デバイスノードを作成する方法について説明します
静的構造体クラス* mydev_class。
mydev_class = class_create(THIS_MODULE、 "mydev "); // クラスの作成
device_create(mydev_class、NULL、なdev_id、 NULL、 "mydev"); //はデバイス番号に係るノード装置を作成する
破壊装置ノード
device_destroy(mydev_class、なdev_id); //デバイスノードが破壊され
class_destroy(mydev_class); //クラス破壊
変性駆動
mydev.c
#include <linuxの/ module.h>
の#include <linuxの/ init.h>
の#include <linuxの/ fs.h>
の#include <linuxの/ cdev.h>
の#include <linuxの/ slab.h>
の#include <linuxの/ device.h>
静的のdev_tなdev_id。
静的構造体CDEV * mydev。
静的構造体クラス* mydev_class。
ssize_tのmydev_read(構造体ファイル*ファイル、チャー__user *データ、size_tのサイズ、loff_t * LOFF)
{
のprintk( "mydev_read \ n");
0を返します。
}
ssize_tのmydev_write(構造体ファイル*ファイル、CONSTチャー__user *データ、size_tのサイズ、loff_t * LOFF)
{
のprintk( "mydev_write \ n");
0を返します。
}
int型mydev_open(のinode構造* iノード、構造体ファイル*ファイル)
{
のprintk( "mydev_open \ N");
0を返します。
}
静的構造体file_operations mydev_fops = {
.owner = THIS_MODULE、
.read = mydev_read、
.open = mydev_open、
.WRITE = mydev_write、
}。
INTは__init静的(ボイド)mydev_init
{
/ *アプリケーション・デバイス番号* /
alloc_chrdev_region(なdev_id&,. 1 ,. 1、 "そのmydevを");
/ *割り当てキャラクタデバイス* /
そのmydev cdev_alloc =();
/ *文字セットデバイス* /
cdev_init(つまりmydev、&mydev_fops)。
/ *登録のキャラクタデバイス* /
cdev_add(mydev、なdev_id、1);
メジャーとマイナー番号* /に/ *印刷要求
のprintk( ":Dの%;マイナー:主要な%D \ N-"、MAJOR(なdev_id)、MINOR(なdev_id));
mydev_class = class_create(THIS_MODULE、 "mydev")。
device_create(mydev_class、NULL、なdev_id、NULL、 "mydev");
0を返します。
}
静的__exit空隙mydev_exit(ボイド)
{
device_destroy(mydev_class、なdev_id)。
class_destroy(mydev_class)。
cdev_del(mydev)。
kfree(mydev)。
unregister_chrdev_region(なdev_id、1)。
}
module_init(mydev_init)。
module_exit(mydev_exit)。
MODULE_LICENSE( "GPL");
再コンパイルモジュールがロードされ
1:表示/ SYSは/ dev /文字ディレクトリ、あなたはいくつかのより多くの情報250を検索します
この時点で、lsのは/ dev / mydevを参照してください、あなたは、/ devディレクトリがすでにmydevを持っています
セブンテスト
各ドライバが終了した後、あなたは、アプリケーションのテストを記述する必要があります
ここで我々のテストプログラムがあります
mydev_test.c
する#include <stdio.hに>
する#includeは<sys / types.h>に
する#include <SYS / stat.h>
の#include <fcntl.h>
する#include <unistd.h>
INTメイン(int型ARGC、CHAR * ARGV [])
{
int型のval = 1。
int型のfd =オープン( "は/ dev / mydev"、O_RDWR);
書き込み(FD&ヴァル、はsizeof(ヴァル));
読み(FD&ヴァル、はsizeof(ヴァル));
0リターン;
}
コンパイル
アームのLinux GCC mydev_test.cの
ロードモジュール
insmodのはmydev.ko
テストプログラムを実行します
./a.outは
、コンソールのプリントを見ることができます
【2639.832633] mydev_open
[2639.833528] mydev_write
[2639.836014] mydev_read
実証正常ドライバ
この記事ではここで終わりにする
----------------
免責事項:この記事はCC 4.0 BY-SAの著作権契約、再版以下CSDNブロガー元の記事「JTの学生を」、です元のソースと、この文へのリンクを含めてください。
オリジナルリンクします。https://blog.csdn.net/weixin_42462202/article/details/99887783