Linux下文字デバイスドライバの構造


まず、概念を明確にしてほしい.
1、駆動とは、必ずカーネルと密接につながっている下位プログラムである.インタフェースはユーザーには表示されません.駆動とカーネルをどのように結びつけるかを考えてみましょう.最初はモジュール(modules)を考えています.モジュールはキャリアのようなもので、容器のようなもので、それを通じて、カーネルが見える領域に書き終わったプログラムを挿入(ロード)して、カーネルに駆動の存在を感知させ、ユーザー空間はシステム呼び出しの形式で駆動に結びつくことができます.そのタスクを完了するために、モジュールを最もよく理解します.
2、駆動はOSの下にあり、OSにハードウェア操作(もちろん駆動はハードウェアではない可能性もある)の論理と下位抽象のパッケージを提供するので、彼は上下を兼ねて、上はOSの駆動呼び出しインタフェースに合致し、下はハードウェアの操作を処理しなければならない.
3、Linuxは特殊で、すべてのデバイスを抽象的にファイルにすると、操作インタフェースが統一され、開発にも便利になります.Linuxのデバイスファイルには、文字デバイス、ブロックデバイス、ネットワークデバイスの3種類があります.
ドライバ(文字デバイスドライバ)を作成するには、次の手順に従います.
1、設備の存在を特徴付ける構造体cdev:
struct cdev{
 		struct kobject kobj; 			 /*    kobject  */
 		struct module *owner; 			 /*    */
struct file_operations *ops;	 /*       */
struct list_head list;
dev_t dev; 		/*   , 32  ,   12       , 20       */
 		unsigned int count;
};

全体の過程はこの構造体をめぐって行われている.彼の各要素に値を割り当て、モジュールを介してカーネルにロードすればよい.私たちは一つ一つ説明します.
場合、kobjectの初期化はcdev_Initの中で完成しましたFs/Char_dev.c :
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
	memset(cdev, 0, sizeof *cdev);
	INIT_LIST_HEAD(&cdev->list);
	kobject_init(&cdev->kobj, &ktype_cdev_default);
	cdev->ops = fops;
}

ここではkobject、list_head、file_operationsも値を付けたり初期化したりしました.パラメータとしてfileが必要ですoperationsは値を割り当てるために使用され、file_operationsには、文字デバイスを操作するために使用可能なすべての関数(インタフェース)が含まれています.ファイルを引き出しましたoperationsは、文字駆動全体のコアであり、すべての処理ロジックをバインドするオブジェクトでもあります.
static const struct file_operations globalmem_fops={  
    .owner = THIS_MODULE,  
    .read = globalmem_read,  
    .write = globalmem_write,  
    .open = globalmem_open,  
    .release = globalmem_release,  
};

ここでは簡単な例ですが、私たちがしなければならないのは、等号の後ろの関数を実現し、その値を割り当てることです.下はfile_operationsのプロトタイプ、完備したインタフェースは、あなたが使っているものを実現するだけでいいです(include/linux/fs.h):
struct file_operations {
	struct module *owner;
	loff_t (*llseek) (struct file *, loff_t, int);
	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
	ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
	int (*readdir) (struct file *, void *, filldir_t);
	unsigned int (*poll) (struct file *, struct poll_table_struct *);
	int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
	int (*mmap) (struct file *, struct vm_area_struct *);
	int (*open) (struct inode *, struct file *);
	int (*flush) (struct file *, fl_owner_t id);
	int (*release) (struct inode *, struct file *);
	int (*fsync) (struct file *, struct dentry *, int datasync);
	int (*aio_fsync) (struct kiocb *, int datasync);
	int (*fasync) (int, struct file *, int);
	int (*lock) (struct file *, int, struct file_lock *);
	ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
	int (*check_flags)(int);
	int (*flock) (struct file *, int, struct file_lock *);
	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
	int (*setlease)(struct file *, long, struct file_lock **);
};

ここで、cdevの初期化によって、私たちはあなたの書いた論理をcdevと結びつけました(file_operationsを通じて)、それから:
    cdev.owner = THIS_MODULE;
直接レプリケーションはcdevと現在のモジュールを関連付けます.次に、
    dev_tdevno =MKDEV(222,0); 
MKDEPマクロを使用して、0のdev_であるプライマリデバイス番号222が生成されるtタイプのデバイス番号変数devnoは、その後、デバイス番号とデバイス構造体cdevを関連付けて、デバイスが間接的にその処理関数を見つけることができ、これを使用して関連を完了します.
    cdev_add(&dev->cdev,devno,1);
well、デバイス構造体の準備ができていて、具体的なデバイス番号も約束されています(このタイプのデバイスが直接具体的な処理を行うことができます).また、現在のモジュールと接続されています.さらに、カーネルにその存在を知らせるには、次の関数を使用します.
    register_chrdev_region(devno,1,"globalmem");
現在のデバイスをカーネルに登録します.これはcdevとは関係ありません.仮想デバイスglobalmemに対してカーネルの登録を行うだけです.彼らのつながりの絆はdevnoです.もちろん、ログアウト関数もあります.
    unregister_chrdev_region(devno,1);
彼らは普通ペアで現れます.
 
このように差は多くなくて、全体の過程と原理はこのようにして、更に詳しくて、Linux駆動開発の詳しい6章をよく読むことができます.非常に詳しく話す.もう一つのblogを見てみると、【Linuxの次の最初のドライバ】は、一例であり、多くの説明が付いており、初歩的な概念を構築することができるはずです.それから漸進的になって、ははは.
 
【本書docドキュメントダウンロード】
.
.