在Linux可加载内核模块中探秘(6)
第一部分:基础知识
第六章:内核守护进程
作者:CoolBoy
今天我们将结束关于LKM基础知识部分的讲解,首先讲讲内核守护进程。
内核守护进程的运行文件是(/sbin/kerneld),从文件的名字就可以猜到,这个进程会一直运行在用户空间,等待着其他动作的发生。当然,有些同学的机器上是没有运行这个进程的,这样就必须在build内核的时候,激活Kerneld选项。
Kerneld的工作原理是这样的:如果内核需要去访问某个设备,而恰好此时这个设备又是不可用的,那么它是不是要产生一个访问错误呢?答案是NO!这时它一定会去找Kerneld帮忙,如果Kerneld有能力提供那个设备的访问接口,那么它就会加载相应的LKM程序(一般作为设备驱动程序),然后内核就可以访问到这个设备了。大家看到,内核守护进程实际上就是为内核提供服务的常驻程序,它能在需要(或者不需要)的时候,加载(或者是卸载)相应的LKM程序,但大家还应该了解的是,上述过程是同时发生于用户空间和内核空间的。
Kerneld存在于用户空间,如果在内核空间运行着的内核需要kerneld提供一个新的模块程序给它,它就会给Kernel发送一个字符串,字符串里存放了需要加载何种模块程序的信息。当然,内核程序也许并不知道某个具体的模块程序(*.OBJ)是什么名字,那么它就会发出一个通用的字符串(例如eth0表示网卡0),这时Kerneld就会去查找/etc/modules.conf列表,从中得到设备的对应的LKM程序名。如下面这行,意思是eth0对应DEC的TULIP驱动程序:
# /etc/modules.conf
alias eth0 tulip
Kerneld从内核得到字符串并找到对应的LKM程序的过程,是在用户空间中完成的。而在内核空间完成的动作,需要调用到四个内核函数。这几个函数其实都调用了系统调用kerneld_send(关于kerneld_send怎样被调用,参见linux/kerneld.h),如下列出了这四个函数:
int request_module (const char *name); 告诉kerneld核心所需要的模块名字(或者别名)
int release_module (const char* name, int waitflag); 卸载一个模块
int delayed_release_module (const char *name); 延迟卸载
int cancel_release_module (const char *name); 取消对delayed_release_module的调用
(注:核心2.2.x使用另外的一种请求加载新模块的机制)
好了,这下我们可以来创建一个我们自己的设备驱动程序了。我们创建的这个程序很简单,它几乎不做什么事情,只是作为一个演示,但如果你有兴趣加些代码,就可以监视TTY(终端)的动作了。下面就是这个程序的代码:
#define MODULE
#define __KERNEL__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*这里什么都没做,只是演示一下*/
static int driver_open(struct inode *i, struct file *f)
{
printk(\"<1>Open Function\\n\");
return 0;
}
/*把将要运用于我们的LKM中的各个函数注册*/
static struct file_operations fops = {
NULL, /*lseek*/
NULL, /*read*/
NULL, /*write*/
NULL, /*readdir*/
NULL, /*select*/
NULL, /*ioctl*/
NULL, /*mmap*/
driver_open, /*open*/
NULL, /*release*/
NULL /*fsync...*/
};
int init_module(void)
{
/*register driver*/
if(register_chrdev(40, \"driver\", &fops)) return -EIO;
return 0;
}
void cleanup_module(void)
{
/*unregister*/
unregister_chrdev(40, \"driver\");
}
其中最最最重要的函数是register_chrdev(...),它将我们的驱动程序注册为主注册号40,如果你访问此驱动,按下面的方法做:
# mknode /dev/driver c 40 0
# insmod driver.o
然后就可以访问此驱动程序了(由于版面有限,这个驱动没做任何事情)。file_operations结构 提供了我们将向系统提供的一切函数。大家可以看到这里仅实现了一个哑元函数OPEN,它只打 印一点东西。不过,很显然,利用上述方法,你可以对你的设备进行任何操作。实作一下,如果你打算记 录下一些有趣的数据(例如键盘按键记录),你可以在你的设备驱动中内建一个缓冲区,然后通过设备设 备输出缓冲区中的内容。
今天就讲到这里了。基础部分的知识介绍完了,不知道大家有什么意见?下章我们将会作很多有趣的“整蛊程序”,欢迎来参观哦!
发布人:Crystal 来自:Linux专区