Linux Driver思考:通向皇宫的通道
传统意义上的Linux Driver仅仅是设备驱动,简言之,和设备有关,如LCD,Camera等等。 但是, 笔者认为,Linux Driver的作用不仅仅局限于此,从广义上讲, Linux Driver提供了一种User Space访问 Kernel中特定Function的通用编程模型,即,平民(User Space中的Application, Process, Lib等)通向皇宫(Kernel)的大道。
如果一个模块提供的Function必须运行于Kernel Space中(可能是设备相关的Function,从而需要访问特权指令或者特权地址空间; 抑或者Function本身是设备无关的,但是访问到了其他的一些运行于Kernel的Function; 甚至于吃饱了没事干,就喜欢把原本可以在User Space中运行的API实现在Kernel中,就是喜欢,你管的着吗?!)。 同时,又希望User Space中的Client能访问使用这些Function, 那么, 将其Adapt成Driver是再合理不过的解决方案了。 这是为什么那??
因为,从理论上来说,Kernel中的API,User Space中的Client是无法直接访问的,只能利用系统调用陷入到内核态后调用。 Linux的系统调用非常多,均已经固定, 如何支持新的Kernel Function的调用那? 有两种方式:
1。 在Kernel中实现一个新的系统调用(添加新的系统调用号),用来支持你实现的新功能。 这真是杀鸡用牛刀的干活,吃力不讨好。 你需要全全负责User Space到Kernel Space的切换,系统调用号的传递,系统调用上下文的保存, 调用后的系统上下文的恢复,Kernel Space向User Space的切换。
2。 复用一个现有的系统函数/调用,来支持你的新功能。 具有抽象意义的系统调用莫过于read,write,open这些为Driver定制的API了。 所以,我们可以简单的将我们的Function Wrapper成Driver需要的open,read,write等,然后,再按照Driver的要求,将我们的Module Wrapper成一个Driver的设备文件并注册到系统中。 这样,User Space中的Client,可以采用传统的Driver的模式来间接访问到我们新加的这些Function,并且,可能这些Function根本和实际的设备没有任何联系。
所以,我们不应该把Linux的Driver狭义的理解为设备驱动, 其实,它是一种通用的User Space访问Kernel Space Function的编程模式。 只要你有这种需求,你就可以实现为Driver,而不需要关心和实现复杂的系统调用过程。 比如Android中的Binder Driver, 根本不是真正的和物理设备打交道, 而仅仅是一个运行于Kernel的Binder Function,但是适配成了Driver,方便User Space中的Client调用。