Introduction to NetBSD loadable kernel modules 翻译
来源:
作者:
时间:2007-12-03
Tag:
点击:
首先,我们要检查一下进程的需求(数据)是否少于sizeof(u_int32_t)字节(实际上是4字节)。我们的read函数总是读取一串4字节的块,同时,为了程序简单和容易理解起见,我们不允许每次读取的数据少于4个字节(uio_uio_resid保存了的要移动到用户空间(数据的)的剩余字节数,uiomove函数自动会将递减)。
这个函数将当前的FIBONACCI数拷贝到用户空间缓冲区中,接着检查是否溢出(只有前面的42个FIBONACCI数适用于u_int32_t),然后计算下一个FIBONACCI数。如果用户空间缓冲区剩余的部分足够大,函数会进入循环并重新开始移动、检查然后计算这一过程,直到缓冲区填充到最大限度或者uiomove(9)返回失败。需要注意的是,对此设备进行的read系统调用永不返回0,因而也不会遇到EOF,所以,此设备会一直产生FIBONACCI数。
如果你熟悉GNU/Linux设备驱动程序编程,你会发现出现错误的时候我们并不返回-ERRNO,以read系统调用为例就是读取数据的字节数;而我们是在成功的时候返回0,失败的时候返回正的错误码。其他的事情NetBSD会自行处理器,我们不需要关心。
加载可加载内核模块
既然设备驱动模块已经完成,我们就需要一个shell脚本以便于在模块加载成功后在/dev中创建所需的设备节点。这个shell脚本(或者程序)总是需要三个参数:模块ID(十进制表示),模块类型(十六进制表示)以及字符设备的主设备号(这与其他类型的LKM不同,例如系统调用模块)。这样看来,我们的脚本非常的简单:
if [ $# -ne 3 ]; then
echo "$0 should only be called from modload(8) with 3 args"
exit 1
fi
首先判断命令行中三个参数是否都存在,如果不是就退出并返回错误码。
for i in 0 1 2 3 4 5 6 7; do
rm -f /dev/fibo$i
mknod /dev/fibo$i c $3 $i
chmod 666 /dev/fibo$i
done
exit 0
最后,我们(重新)创建需要的特定设备节点。
现在,我们的模块可以第一次试运行了。
编译模块然后用下面的命令将其加载(这需要超级用户的身份):
modload -e fibo_lkmentry -p fibo_post.sh fibo.o
如果一切顺利,modstat(8)程序会有这么一个类似的反馈:
Type Id Off Loadaddr Size Info Rev Module Name
DEV 0 29 dca4f000 0004 dca4f260 1 fibo
测试可加载内核模块
为了测试你的新内核模块,我们需要一个小程序,只是从/dev/fibo0中读取一个32-bit无符号整数然后将其打印到标准输出中。
看下面的例程:
#define DEVICE "/dev/fibo0"
int
main(int argc, char **argv)
{
u_int32_t val;
int fd, ret;
if ((fd = open(DEVICE, O_RDONLY)) < 0)
err(1, "unable to open " DEVICE);
while ((ret = read(fd, &val, sizeof(val))) == sizeof(val))
printf("%u\n", val);
if (ret < 0)
err(2, "read(" DEVICE ")");
close(fd);
return 0;
}
这个测试例程运行时,会输出小于2971215074的FIBONACCI数直到被中断或者杀死。
你可以运行下面的命令(用超级用户)将模块卸载掉:
modunload -n fibo
包含完整的代码和Mafile的打包文件在这里可以找到。我希望你会喜欢这篇NetBSD可加载模块系统的简短介绍。如果你有疑问或者想有什么要告诉我,请直接发邮件给我benny@xfce.org。
0
