dev_t devno = MKDEV(mem_major, 0)
dev_t 是设备这种类型
MEDEV是宏构造主次设备号
静态分配 if(mem_major)为大于0
如果mem_major==0则动态分配
15
静态分配:
使用register_chrdev_region函数
动态分配:
由内核去找设备号
使用alloc_chrdev_region分配设备号
缺点:无法再安装驱动前创建设备文件。
注销设备号:
使用函数:unregister_chrdev_region
手动创建
mknod filename typle major minor
设备文件起桥梁的作用 譬如read的时候传达给驱动程序
驱动程序再执行到硬件中然后返回到设备文件中。
在liNUX字符设备驱动设计中有三种很重要的数据结构
struct file:代表一个打开的文件。系统中每个打开的文件在内核空间中都有一个关联的stuct file.
struct inode:用来记录文件的物理信息。
struct file_operations:由函数指针构成。
右边是函数指针=左边函数名字。
找驱动函数去执行。绑着驱动程序。
在2.6内核中字符设备用struct cdev来描叙。其注册分三步:
分配cdev 初始化cdev 添加cdev
分配使用cdev_alloc函数:
初始化使用cdev_init函数:
添加使用 cdev_add函数:
完成驱动程序的注册后下一步 file_operation的函数需要我们去实现。
open方法:打开
read write:
读和写都完成类似的工作:从设备中读取数据到用户空间;
将数据传递给驱动程序。
size_t loff_t char_user 都是类型。
read和 write 方法的buff 参数是用户空间指针,因此它都不能被内核代码直接引用:
用户空间指针在内核空间时可能根本是无效的 没有那个地址映射。
内核提供了专门的函数访问用户空间的指针:
如copy_from_user 和copy_to_user 两个函数。我们的read 和write是站在用户的角度来看的
用户需要读 则要到用户。分析数据的流向。
字符设备的注销 cdev_del 函数来完成。
设备号作用:主设备号用来标识与设备文件相连的驱动程序;
次设备号被驱动程序用来辨别操作哪个设备。
主设备号用来反映设备类型次设备号用来区分同类型的设备。
内核中如何描述设备号:
dev_t实质为unsigned int32 位整数高12位为主设备号低20位为此设备号
如何从dev_t中分解出主次设备号:
MAJOR(dev_t dev)
MINOR(dev_t dev)
mem_fops是操作里的 file_option
设备号》初始化》字符设备注册三步(直接定义的就需要分配)
为设备分配内存:
为设备描述结构分配内存: