内核空间和用户空间如何有效地进行通信是我们进行内核编程经常需要面对的问题,其中又以文件相关的通信方式居多,最为常用的可能就是proc文件了,本文主要比较这些通信方式,分析其在特定环境下的优劣,试图探讨如何更加合理地应用这些通信方式。
对OS略微有些了解的人都清楚,一般的系统空间都是分为内核空间和用户空间两部分的,其中处于内核空间的运行实体对包括用户空间在内的整个系统空间拥有完全的访问权限,而处于用户空间的运行实体只能通过内核暴露给用户的一些接口访问处于内核空间的资源。这些接口,通常的表现形式为“系统调用”,而系统调用本质上也是一种通信,由用户空间的实体发请求给内核,内核将采取特定的动作,并将结果返回给用户空间的实体。所以,我们可以统称这些接口为内核空间和用户空间的通信接口,以下简称为“接口”。
在内核的编程中,第三方通过添加系统调用的方式来添加这些接口,通常是不被鼓励的,因为这要占用系统调用号,可能和后续的官方系统调用产生冲突。我曾经有过设计一个动态系统调用绑定机制的idea,可当我逐渐了解到这将给内核造成混乱的局面后,这个念头也就逐渐打消了。
一度中ioctl()被开发人员们“滥用”,引起了Linux社区的普遍反感;接下来,他们发现了proc文件系统这根救命稻草,这又再次招致了大家的“趋之若鹜”;如今/proc已经变得肮脏不堪,已经超越了提供process信息的本意,为了减轻/proc的负担,Linux-2.6.x在引入新的设备模型的同时,又发明了一个崭新的文件系统--sysfs,可这究竟能不能扭转目前的混乱局面,我们将拭目以待!
proc文件系统应该只存放和进程相关的信息,其他的一些信息都应该放到sysfs中,可惜的是在从2.4向2.6转变的过程中,这个转变并没有发生,我想很有可能是考虑到兼容性的问题,也许以后永远都不会发生,既成的现实改变起来也确实比较困难,可以后的东西就都应该放到sysfs中了。
相对proc文件系统,sys(system)文件系统就显得更加具有包容性,从它的取名上,我们就可以猜出它的目标是整个系统的信息,其中各级目录的安排会使系统变得井井有条,层次分明,可这个目录的整洁也是需要依靠我们大家的共同遵守规则来实现的,不然它将永远只是美好的愿望。
ioctl(),setsockopt()和getsockopt()此类接口方式也并不是一无是处,如果某个设备的属性是描述符相关而非设备全局的,那么我们还是可以通过这些来控制设备的属性的。
同样的系统调用也是有它的市场的,它通常用于协助用户态的进程完成在内核态才能完成或者是更加有效完成的任务。
至于一些用虚拟的设备来实现的接口,还是应该依据你所实现的功能的模型来选用。比如说伪终端就是作为字符设备来实现的,理解起来也更加的容易。
socket等的应用场合应该是面向消息的通信,例如udev的实现方式就是内核通过netlink socket向处于用户空间的udev守护进程广播消息。
目前想到的只有以上几类了,以后如果再有遇到,再补充也不迟。以前我blog中提到过的创建虚拟的文件系统也不失一个办法,但我奉劝你还是不要这样做,除非你有充足的理由。
似乎又是虎头蛇尾!不知所云!
阅读(1378) | 评论(0) | 转发(0) |