デバイスドライバーの学習を始める

1.Linux ではデバイスはどのカテゴリに分類されますか?

ここに画像の説明を挿入します
ここに画像の説明を挿入します

2. デバイスドライバーの階層

ここに画像の説明を挿入します
ここに画像の説明を挿入します

3. デバイスサービスを要求するユーザープロセスのプロセス

ここに画像の説明を挿入します

4. 運転のあらゆる部分

ドライバーとは何ですか?

(1) ドライバーはソフトウェアとハ​​ードウェアの間の架け橋です。
(2) ドライバーは、オペレーティング システムに追加される特別なプログラムです。
(3) ドライバーは、コンピューターとデバイスの通信を可能にする特別なプログラムです。

なぜドライバーが必要なのでしょうか?

(1) ソフトウェアシステムは、接続されるデバイスとその機能を直接識別することができません。
(2) ハードウェアデバイスは電気信号のみを理解でき、ソフトウェアシステムが発行するコマンドを直接理解することはできません。

ドライバーを作ったのは誰ですか?

ドライバーは、オペレーティング システムに基づいてハードウェア メーカーによって作成された構成ファイルです。

ドライバーの役割

ドライバーはソフトウェアとハ​​ードウェアの間の架け橋です

(1) ハードウェア自体の機能をオペレーティングシステムに伝え、ハードウェア装置の電子信号とオペレーティングシステムやソフトウェアの高級プログラミング言語(javaなど)との相互翻訳を完了します。
(2) オペレーティング システムの標準命令をハードウェア デバイスに伝達します。
(3) オペレーティング システムは、サウンド カードに音楽を再生させるなど、特定のハードウェアを使用する必要がある場合、まず対応する命令をサウンド カード ドライバーに送信します。その後、サウンド カード ドライバーのみが理解できる電子信号コマンドに即座に変換され、サウンド カードが音楽を再生できるようになります。

5.file_operations() 構造体の機能は何ですか?

file_operations 構造体は、デバイスの読み取り、書き込み、保存などを完了します。これらの操作はすべて、file_operations 構造体に格納されている関数ポインターによって処理されます。これらの関数ポインターが指す関数は、ドライバー モジュールに実装する必要があります。

struct file_operations {
	struct module *owner;    //拥有该结构的模块的指针,一般为THIS_MODULES
	......
	int (*mmap) (struct file *, struct vm_area_struct *);    //用于请求将设备内存映射到进程地址空间
	......
	int (*open) (struct inode *, struct file *);    //打开
	......
}

6.デバイス番号はドライバー内でどのような役割を果たしますか? なぜメジャーデバイス番号とマイナーデバイス番号が必要なのでしょうか?

各ファイルはデバイスであり、デバイス番号はメジャーデバイス番号とマイナーデバイス番号で構成されます。

メジャーデバイス番号:

  1. 一般に、メジャー デバイス番号がドライバーに対応すると考えられています。
  2. 1 つのドライバーで複数のデバイスを管理できます。つまり、1 つのメジャー デバイス番号が複数のデバイスに対応します。
  3. 1 つのメジャー デバイス番号が複数のドライバーに対応することもできます

マイナーデバイス番号:

  1. マイナーデバイス番号はデバイスに対応します

この種のデバイスは 1 つのドライバーで複数管理でき、マイナーデバイス番号は 20 桁であるため、デバイスの数は 2 の 20 乗まで可能ですが、実際にはこれほど多くのデバイスを管理することは不可能です。

7. キャラクターデバイスのドライバー登録・登録解除機能とは何ですか? なぜ登録とキャンセルが必要なのでしょうか?

キャラクターデバイスドライバーの登録関数:

static inline int register_chrdev(unsigned int major, const char *name,
				  const struct file_operations *fops)
{
	return __register_chrdev(major, 0, 256, name, fops);
}
/*__register_chrdev() - 创建并注册一个占有较小大小的字符设备
  major:主设备号,当用户设置为0时,内核会动态分配一个设备号。
  baseminor: 次设备号,要在一定范围内从0开始
  count: 次设备号的范围
  name: 设备名称
  fops: 文件系统的接口指针
  
  如果major == 0,此函数将动态分配一个major并返回它的编号。
  如果major > 0,此函数将尝试使用给定的主设备号来保留设备,成功时将返回0。
  
  失败时返回-ve errno。
*/
int __register_chrdev(unsigned int major, unsigned int baseminor,
		      unsigned int count, const char *name,
		      const struct file_operations *fops)
{
	struct char_device_struct *cd;
	struct cdev *cdev;
	int err = -ENOMEM;

	cd = __register_chrdev_region(major, baseminor, count, name);	//注册一个主设备号和一个一定范围内具体的次设备号
	if (IS_ERR(cd))
		return PTR_ERR(cd);

	cdev = cdev_alloc();	//分配空间
	if (!cdev)
		goto out2;
	//对cdev进行赋值操作
	cdev->owner = fops->owner;
	cdev->ops = fops;
	kobject_set_name(&cdev->kobj, "%s", name);

	err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);	//把这个设备添加到系统中
	if (err)
		goto out;

	cd->cdev = cdev;	//完成cd与cdev的关联

	return major ? 0 : cd->major;
out:
	kobject_put(&cdev->kobj);
out2:
	kfree(__unregister_chrdev_region(cd->major, baseminor, count));
	return err;
}

キャラクターデバイスドライバーの関数の登録を解除します。

static inline void unregister_chrdev(unsigned int major, const char *name)
{
	__unregister_chrdev(major, 0, 256, name);
}
void __unregister_chrdev(unsigned int major, unsigned int baseminor,
			 unsigned int count, const char *name)
{
	struct char_device_struct *cd;

	cd = __unregister_chrdev_region(major, baseminor, count);
	if (cd && cd->cdev)
		cdev_del(cd->cdev);
	kfree(cd);
}

登録とは、使用する対応するデバイスドライバーを生成することです。

ログオフするとメモリが解放され、他のプロセスが実行できるようになります。

8.I/OポートとI/Oメモリ

I/O 空間に配置されている場合は、I/O ポートと呼ばれることが多い

メモリ空間に配置される場合、対応するメモリ空間は I/O メモリと呼ばれます

ここに画像の説明を挿入します

9. ユーザプログラム内のキャラクタデバイス内のグローバルメモリの読み書き

ここに画像の説明を挿入します

10. ブロックデバイスドライバーの登録

ここに画像の説明を挿入します

11. ブロックデバイスとキャラクターデバイスの違い

ここに画像の説明を挿入します

(1) ファイル システムはブロック デバイスにマウントできますが、キャラクタ デバイスにはマウントできません。ファイル システムはデータをブロックに保存できる必要があり、データをランダムに読み書きできる必要があるため、これは明らかにランダム アクセスによってもたらされる利点です。

(2) ブロックデバイスを通過するデータは、キャラクタデバイスを操作する場合と比較して、データバッファ層を通過する必要があります。つまり、アプリケーションがブロックデバイスにデータを転送するとき、アプリケーションはキャラクタデバイスと直接対話しませんが、システム全体のパフォーマンス (スループット) を向上させるには、データを保存するために中間バッファ層を通過する必要があり、そうして初めてデータを使用できるようになります。

(3) キャラクター ドライバーのインターフェイスは比較的明確で使いやすいですが、ブロック ドライバーのインターフェイスは少し複雑です。これには 2 つの理由があります: 1 つはその歴史のためです - ブロック ドライバー インターフェイスは最初のバージョンから Linux のすべてのバージョンに含まれており、変更または改善するのが難しいことがわかっています; パフォーマンス、遅いキャラクターのデバイス ドライバーは望ましくありませんが、それでも許容可能ですただし、ブロックドライバーが遅いと、システム全体のパフォーマンスに影響します。したがって、ブロック ドライバーのインターフェイス設計は、速度要件の影響を受けることがよくあります。

おすすめ

転載: blog.csdn.net/qq_58538265/article/details/133916635