キャラクタデバイスドライバフレームワーク
(はじめに)
私はシンプルなフロント書くのLinuxキャラクタデバイスドライバを。そして、単にキャラクタデバイスドライバフレームワークを見てください。
まず、重要なデータ構造
Linuxのキャラクタデバイスでは、そこに三つの重要なデータ構造があり、すなわち:file_operationsをストラクト、構造体ファイルとのinode構造
シンプルに説明するために、以下の
1、構造体file_operations
この構造は、デバイスのキャラクタを操作する相関関数を達成するために、デバイスドライバに相当します
/* 只介绍部分struct file_operations结构体的成员 */
struct file_operations {
/* struct module 这个成员不是一个操作; 它是一个指向拥有这个结构体的模块指针。
* 这个成员用来在它还被使用时阻止模块被卸载。一般初始化为 THIS_MODULE,
*/
struct module *owner;
/* llseek 函数用来改变文件中当前的读/写的位置,如果这个函数指针是NULL,内核中
* 缺省的实现通过修改filp->f_pos进行移位
*/
loff_t (*llseek) (struct file *, loff_t, int);
/* read函数用来从设备中获取数据。如果这个函数指针是NULL,以 -EINVAL 失败返回给
* read 系统调用,一个非负返回值代表了成功读取的字节数。
*/
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
/* write函数用来发送数据给设备。如果这个函数指针是NULL,以 -EINVAL 失败返回给
* write 系统调用,一个非负返回值代表了成功读取的字节数。
*/
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
/* poll 函数是: poll, epoll 和 select 这三个系统调用的后端。这三个系统调用都用作查询对一个
* 或者多个文件描述符的读或写是否会阻塞。poll函数应返回一个位掩码指示是否非阻塞的读或
* 者写是可能的。并且给内核提供信息,用来使调用的的进程睡眠,直到读写操作变为可能。
* 如果一个驱动的 poll 指针为 NULL, 设备假定为不阻塞地可读可写。
*/
unsigned int (*poll) (struct file *, struct poll_table_struct *);
/* ioctl 函数 为 ioctl() 系统调用提供了发出设备特定命令的方法
* 如果一个驱动的 ioctl 指针为 NULL, 对于任何未事先定义的请
* 求返回 -ENOTTY, 系统调用返回一个错误
*/
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
/* mmap 用来请求将设备内存映射到进程的地址空间,
* 如果这个指针是 NULL, mmap 系统调用返回 -ENODEV.
*/
int (*mmap) (struct file *, struct vm_area_struct *);
/* open成员是 open 系统调用的后端,通常是对设备文件进行的第一个操作
* 如果这个指针是 NULL, 设备打开一直成功, 但是你的驱动不会得到通知.
*/
int (*open) (struct inode *, struct file *);
/* release成员是 close系统调用的后端,在文件结构被释放时引用这个操作。
* 如同open,release成员也可以为NULL。
*/
int (*release) (struct inode *, struct file *);
/* fasync这个操作用来通知设备它的 FASYNC 标志的改变(异步通知)
* 如果这个成员是 NULL, 驱动不支持异步通知。
*/
int (*fasync) (int, struct file *, int);
};
2、構造体ファイル
この構造は、管理するために、構造体のファイル構造を持つことになります、各ファイルを開いて、ファイルを開いて記述されています
/* 只介绍部分struct file结构体的成员 */
struct file {
/* 文件模式确定文件是可读的或者是可写的(或者都是),
* 通过位 FMODE_READ 和FMODE_WRITE 描述
*/
mode_t f_mode;
/* 文件当前的读写位置. 如果驱动需要知到文件中的当前位置,可以读这个值,但是不应该改变它。
* 在fops 的 read 和 write 以最后的一个参数传入,来代替直接使用f_pos成员,在fops的llseek方法中
* 通过改变f_pos 成员来改变,文件的读写位置
*/
loff_t f_pos;
/* 文件的标志。例如 O_REONLY, O_NONBLOCK, 和 O_SYNC。驱动通过检查O_NONBLOCK标志
* 来查看是否请求非阻塞操作,其他标志一般比较少用。
*/
unsigned int f_flags;
/* 和文件关联的操作*/
const struct file_operations *f_op;
/* 这个成员通常用来指向分配的数据,通常在fops->open 成员函数里面指定。
* 如果使用了这个成员必须在fops->release 成员中释放。
*/
void *private_data;
};
3、構造体のinode
ディスク上のstruct inodeファイルを記述するために使用されます。inode構造体は、ファイルに関する情報が豊富に含まれていますが、この構造の2人のだけのメンバーがドライバを書くための便利なコードです
/* 只介绍部分struct inode结构体的成员 */
struct inode {
/* 对于代表设备文件的节点, 这个成员包含实际的设备编号. */
dev_t i_rdev;
union {
struct pipe_inode_info *i_pipe;
/* 当节点指的是一个块设备文件时,代表块设备。*/
struct block_device *i_bdev;
/* 当节点指的是一个字符设备文件时,代表字符设备。*/
struct cdev *i_cdev;
};
}
二、Linuxのソースコード解析フレーム
カーネルドライバへのシステムコールは、以下のように呼び出し(例えば、オープンシステムコールで、他の同様のシステムコール)
(エントリ機能システムコールカーネルcalls.Sでこの文書/)
SYS_OPEN
do_sys_open
FD = get_unused_fd(); //このプロセスはファイルディスクリプタ使用見つけることができなかった
構造体ファイルを* F = do_filp_open(DFD、TMP、旗、MODE); //構築し、構造体のファイル構造に配置
(&のNd、フラグ)nameidata_to_filpを、
__dentry_open(ND->のdentry、のNd - > MNT、旗、財投、NULL);
IF(オープン&& F-> f_opが)!第五__dentry_openのパラメータとして関数ポインタを開き//
オープンオープン= F-> f_op->; //取得FOPS開放部材
(開く){IF
エラー=オープン(iノード、F); //関数を開く関数を呼び出します
}
第三に、図のフレーム。
< 以上に取りつかれ >ブロガーは、フレームのより詳細な図を持っているので、直接の引用が来て