本文目标
本文在上一节的基础上,采用可以指定主设备号,次设备号,手动申请dev_t和自动申请dev_t的API,封装一个全局的对象结构体并用private_data在方法间传递,减少全局变量使用,寄存器操作改用readl和writel,引入cdev、class、device对象。
驱动里面的全局结构体是对象私有数据,fops是对象内部的操作函数,可以通过系统调用对外public。
cdev、class、device应该是驱动对象的各种父类,用来抽象各种子系统的数据和行为,以便实现统一框架。
以上是我个人理解,没有严格意义上的验证。
API介绍
I/O内存访问函数:
采用ioremap将物理地址映射到虚拟地址之后,我们可以直接通过指针访问这些地址,但是Linux内核不建议这么做,而是提供了一系列函数。
1、读操作函数
u8 readb(const volatile void __iomem *addr);
u16 readw(const volatile void __iomem *addr);
u32 readl(const volatile void __iomem *addr);
从返回值类型可以看出其功能。
2、写操作函数
void writeb(u8 value,volatile void __iomem *addr);
void writew(u16 value,volatile void __iomem *addr);
void writel(u32 value,volatile void __iomem *addr);
3、register_chrdev的不足:
ret = register_chrdev(major,module_name,&ldd2_fops);
需要提前知道系统里面不冲突的major,使用过程中发现代码里写的100这个号不能用,难道系统集成商需要把程序员叫过来重新改?
另外,这个API会把一个主设备号下面的2^20-1个次设备号全部用掉。
所以,自然而然有人提出了以下api:
a、指定主设备号,和次设备号个数,一次n个,不浪费。
int register_chrdev_region(dev_t from,unsigned count