简单的字符串驱动程序 (读《linux驱动程序》)

1.主设备号和次设备号node

下图中,“”5月”的前两列分别是主设备号和次设备号,主设备号用来标识设备对应的驱动程序,次设备号用来肯定设备文件所指的设备。linux

在内核,dev_t类型用来保存设备编号,位于文件<linux/types.h>。目前版本(3.1),dev_t 是一个unsigned int 类型,12位用来标识主版本号,20位用来标识次版本号,使用 MAJOR(dev_t dev)MINOR (dev_t dev)两个宏来获取主版本号和次版本号.  使用MKDEV(int major,int minor) 获取dev_t类型的版本号。函数

主版本号的静态分配和动态分配:指针

在2.4版本以前,使用register_chrdev(unsigned int major, const char *name,const struct file_operations *fops); 进行注册,若是major 为0则自动分配 主版本号。blog

静态分配 , 使用 register_chrdev_region(dev_t first,unsigned int count, char * name) ;字符串

动态分配,使用 alloc_chrdev_region(dev_t *dev, unsigned int firstminor,unsigned int count, char * name);it

 

2.文件操做io

struct file_operations class

经过上面的操做获取了设备号,可是尚未将任何驱动程序连接到 你获取的设备号,linux内核采用 struct file_operations  <linux/fs.h>来创建链接,这个结构定义了一些列的文件操做的函数指针,例如open read write,ioctl 等,是否是很熟悉? 用户程序调用了 open read 等系统调用,而后通过 VFS层,在vfs层拿到 struct file 指针,经过调用f_op(struct file_operations )的函数指针实现驱动程序的调用,详情请参见read_write.c。兼容性

 

struct file

file结构表明一个打开的文件,它有内核在调用open 时建立,直到最后的close函数,在文件的全部实例都被关闭以后内核才会释放、

struct inode

内核用inode表示文件,与file 不一样的是,file 随着open 系统调用的屡次调用打开同一个文件,内核中会有多个struct file的实例,可是inode实例只有一个。

dev_t i_rdev  设备号,这个字段的类型在2.5中发生了变化,为了兼容性,内核中增长了两个新的宏,用来获取主、次设备号

unsigned int iminor(struct inode * inode);

unsigned int imajor(struct inode * inode);

 

3.注册驱动

初始化

使用struct cdev <linux/cdev.h>结构来标示字符串设备, struct cdev 结构有两种初始化方式, struct cdev * cdev_alloc()和 void cdev_init(struct cdev * cdev, struct file_operations * fops)。

添加

使用 int cdev_add(struct cdev * cdev, dev_t num, unsigned int count);

删除

使用 void cdev_del(struct cdev * cdev);

4.用户态与内核态的数据交互。

unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) ;

unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);