星期一, 十一月 06, 2006

和内核一起做些事情:/proc

首先,我尝试搬抄一下使用/proc文件访问内核的方式。这个方式在以前的书本上写要注册一个proc_dir_entry结构体的内容,然后注册等。但是现在这些情况有所变化。如果只是向用户输出(也就是用户只读),那么只需要写一个读取的方法就好了,注册的方法很简单。

下面用代码说明:
static int procfile_read(char *buffer,
char **buffer_location,// Buffer
off_t offset, // current offset to read
int buffer_length,
int *eof,
int *data)
{
static char mybuffer[128];
static int readcount = 0;
int len;

if(offset > 0){
return 0;
}

readcount ++;
len = sprintf(mybuffer, "This is %d time to read me.\n", readcount);
*eof = 1;
return len;
}
代码主要来自这个实例,虽然是2.4内核的,可是效果在999之内还是不错的。
需要注意的是读取函数的参数发生了变化。不过,我的编译器还是一再提醒我注册时指针参数不匹配的问题,不知道指的是哪一个参数?

注册:
create_proc_read_entry("hello", 0, NULL, procfile_read, NULL);
注销:
remove_proc_entry("hello", NULL);
这里为了简单都采用了默认的参数,直接放到了/proc/hello这个位置上。

采用文件名来操作的确比使用inode方便的多了。

星期四, 十一月 02, 2006

Linux 下驱动程序的开发简单入门步骤

2.6内核的初学者笔记

第一步,下载一个内核源代码并编译安装。
这里需要注意的问题是需要将自己根目录所在的硬盘的驱动和文件系统的驱动全部直接编译到内核中。
否则在启动的时候会出现问题,在装入根目录的阶段停止不前。
建议是第一次宁可多选择一些,如SICI和ATA-2(并口硬盘),以及SATA等直接编译进系统。
而Ext2和Ext3也同样处理。
注意不要将grub菜单中原来系统的启动内核项目取消,也不要急着删除原来的旧内核和模块文件。
如果menu.lst中对原内核和驱动的引用为没有版本号的连接文件,如/boot/vmlinux等,
请改为绝对的文件名。因为一会儿安装新内核的时候这些连接会改变。
这样可以防止万一新的内核不能启动的情况下还可以恢复使用。
此外,优化内核的编译设定,这也算是一种乐趣。
千万不要忙着删除内核代码,这里是很大的文档宝库。

第二,参照书本些一个最为简单的模块。
就是能在进入和退出内核的时候显示两条日志即可。比如:


#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

static int hello_init(void)
{
printk(KERN_ALERT "Hello, linux kernel module\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, I've created a linux kernel module sucessfully\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jason Xing <xsinuz<at>someone.at.prv<");

建议是最好能按照Linux内核的传统代码风格编写。这个可以在内核中找到很多demo。
注意代码和2.4的不同,比如必须自己注册入口和出口方法。

第三,编译这个模块。
请仔细了解本版本下内核编译的方法。有用的资料依然是内核中那些已经存在的Makefile。
可以照着写一个:

obj-m := hello-1.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

之所以能写的如此简单是由于Kbuild的帮助。

然后执行make编译:

make
make -C /lib/modules/2.6.18/build SUBDIRS=/home/jason/projects/test/kernel-dev/hello1 modules
make[1]: Entering directory `/usr/src/linux-2.6.18'
CC [M] /home/jason/projects/test/kernel-dev/hello1/hello-1.o
Building modules, stage 2.
MODPOST
CC /home/jason/projects/test/kernel-dev/hello1/hello-1.mod.o
LD [M] /home/jason/projects/test/kernel-dev/hello1/hello-1.ko
make[1]: Leaving directory `/usr/src/linux-2.6.18'


得到了内核模块文件 hello-1.ko!

第四,测试。
这里需要知道三个命令:lsmod,insmod, rmmod。从名字上也大体应该知道他们的作用了。
不过这个简单的模块并不能用显示出来。
在插入内核后我们可以通过dmesg看到我们写入的第一条信息。卸除后可以看到第二条信息。
注意:这里需要管理员权限才可一对内核操作。


第五,下一步。
买一本《Linux内核驱动开发》也许是必要的。不过有点贵,而且是英文的,真的要考虑一下。

----
参考文献