前言
我们知道Linux源码是C语言,而继承是面向对象的很重要的思想,Linux内核中也通过开发者的智慧实现了继承。
嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关注本博主并订阅本专栏,一起讨论一起学习。现在关注就是老粉啦!
目录
- 前言
- 封装的思想
- 继承实现方式
- 参考资料
封装的思想
在面向对象编程中,封装和继承其实是不分开的:封装就是为了更好地继承。我们将几个类共同的一些属性和方法抽取出来,封装成一个类,就是为了通过继承最大化地实现代码复用。通过继承,子类可以直接使用父类中的属性和方法。
如Linux内核中的网卡设备,不同厂家的网卡、不同速度的网卡,以及相同厂家不同品牌的网卡,它们的读写操作基本上都是一样的,都通过标准的网络协议传输数据,唯一不同的就是不同网卡之间存在一些差异,如I/O寄存器、I/O内存地址、中断号等硬件资源不相同
遇到这些设备,我们完全不必给每个类型的网卡都实现一个结构体。我们可以将各个网卡一些相同的属性抽取出来,构建一个通用的结构体net_device,然后通过一个私有指针,指向每个网卡各自不同的属性和方法,通过这种设计可以最大程度地实现代码复用。如Linux内核中的net_device结构体。
继承实现方式
可以通过内嵌结构体,即在子类中加入父类的结构体,然后就可以在子类基础上扩展自己的属性,同时子类也可以用父类的一些属性。
使用私有指针,例如在net_device
结构体定义中,我们可以看到一个私有指针成员变量:ml_priv
。当我们使用该结构体类型定义不同的变量来表示不同型号的网卡设备时,这个私有指针就会指向各个网卡自身扩展的一些属性。
当然最常见的还是private_data
变量,private_data
是一个结构体或类中的成员变量,用于指向该设备的私有数据。这个变量的作用是为了让驱动程序可以在设备和设备文件之间建立联系。
需要注意的是,private_data
变量不是内核中的全局变量,而是每个设备文件独有的。也就是说,每个设备文件都有自己独立的private_data
变量,因此,不同的设备文件可以使用不同的私有数据,这样就使得驱动程序更加灵活。
使用的时候一般是在open函数中就指定private_data
变量为本设备文件:
static int chrdevTest_open(struct inode *inode, struct file *filp) {filp->private_data = &chrdevTest;return 0;
}
然后在需要的时候再取出来:
struct chrdevTest_dev *dev = (struct chrdevTest_dev *)filp->private_data;
参考资料
Linux驱动开发中private_data变量的理解