《linux2.6驱动编程第一例:hello,world的实现步骤》已由 gongji110 于2008-4-14 发表于红联http://www.linuxdiyf.com,作为基于linux 2.6内核驱动开发的一个最简单也是最经典的例子,我写于此,作为对gongji110文章的一个补充。hello,word例子出自于《Linux 设备驱动开发详解》,华清远见 宋宝华编著。具体步骤如下:
1.编写代码:
/*
* hello.c -- the example of printf "hello world!" in the screen of driver program
*/
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");/* declare the license of the module ,it is necessary */
static int hello_init(void)
{
printk(KERN_EMERG "Hello World enter!\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_EMERG "Hello world exit!\n");
}
module_init(hello_init); /* load the module */
module_exit(hello_exit); /* unload the module */
/* before is some decription of the model,not necessary */
MODULE_AUTHOR("vivi.wei");
MODULE_DESCRIPTION("This is an example of programming driver!");
MODULE_ALIAS(“a simplest module”);
简要说明:
把自己的程序代码包含到内核中一两种方法,一是直接编译到内核,二是编译成模块,动态加载。在嵌入式产品开发之初,一般编译成模块用于调制,当产品发布时再编译到内核,这里只是片面的阐述一下,具体请参考Linux驱动开发相关资料。本例子我们编译成模块来加载运行。该模块只包含内核模块加载函数、卸载函数、和对Dual BSD/GPL许可权限的声明及一些描述信息。编译它会产生hello.ko目标文件,通过"insmod ./hello.ko" 命令可以加载它,通过命令“rmmod hello ”可以卸载它 ,加载时输出“Hello World enter! ”卸载时输出“Hello Word exit! ”。
2.编译代码:
在代码的目录下建立一个Makefile文件,将下面的语句写入其中:
obj-m := hello.o
简单说明:
obj-m 表示要由hello.c文件编译得到hello.o,并作为模块编译,obj-y 则表示要连接进内核,obj-x 则目标不会被编译。
执行如下命令编译代码:
make -C /lib/modules/2.6.25/build/ M=/D/weijing/hello/ modules
简单说明:/lib/modules/2.6.25/ 是我的内核模块的安装路径,就是编译内核的时候"make modules_install"是在/lib/modules/目录下生成的系统源码包;M=/D/weijing/hello/ 是我 存放hello.c多路径。当然,也可以按照红联上gongji110前辈的命令编译,原理一样。
编译完成后将出现下列代码:
[root@localhost ~]# make -C /lib/modules/2.6.25/build/ M=/D/weijing/hello/ modules
make: Entering directory `/usr/src/kernels/linux-2.6.25'
CC [M] /D/weijing/hello/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /D/weijing/hello/hello.o.mod.o
LD [M] /D/weijing/hello/hello.ko
make: Leaving directory `/usr/src/kernels/linux-2.6.25'
[root@localhost ~]#
这时就表示编译成功,在目录下将产生hello.ko文件。2.6以前的版本是生成.o文件,Makefile文件也不一样,在此不累叙。我在编译的时候还出现了点意外,弄了好长时间,就是报错:MODPOST 0 modules,后面两行 CC...LD...都没有,所以也就生成不了.ko文件,我当时用的是2.6.8.1内核版本,配置编译内核后make modules_install,在lib/modules/下也看到了模块,就是生成不了.ko文件,现在我知道原因是内核源码没有包含进去,自然也就MODPOST 0 modules 了,后来下了当时最新的内核2.6.25,配置编译安装,也就是make modules_install 之后make install;重启系统后就可以选择进入目前新装的系统,我的目前是2.6.25,好像现在高版本的内核升级很智能了,不用你复制boot相关的文件等等。编译了内核,也有了新的源码包,编译驱动的时候也就不会MODPOST 0 modules了。
3.执行代码,加载驱动模块:
insmod ./hello.ko即可加载模块。这时我们就可以看到期待已久的Hello,world了。见截图。
4.卸载驱动模块:rmmod hello.
加载模块后就可在屏幕上看到如下信息:Hello world enter.
卸载时就可在屏幕上看到如下信息:hello world exit.
有的执行的时候竟然什么也没有,既没有报错,也没有任何输出
这时你可以在/var/log/messages或者/var/log/kern.log这个文件中看到以上输出信息(使用cat /var/log/messages一般在最下面几行)。
那么怎么才能在屏幕上打印出这些信息呢?
这时你必须对源文件做如下修改:
<1> 将"printk(KERN_ALERT "Hello World enter!\n");”一句中的“KERN_ALERT”换成"KERN_EMERG"以提高内核打印的优先级(0);
<2> 同理将printk(KERN_ALERT "Hello world exit!\n");改成printk(KERN_ALERT "Hello world exit!\n");
重新编译,加载,你就可在屏幕上看到输出信息了。
后记:
说实话,看到屏幕出现那几个字母的时候,是凌晨3:01,遗憾我没有把那历史的时刻记录下来,对我来说所非常的有意义,可能有弟兄会说,这么简单的东西,值得那样子吗,其实我买了一块ARM9的开发板,优龙的FS2410,移植了2.6.8.1,一直没有能让自己的驱动来点亮个LED,因为用的是2.6的内核,文档上给的程序是基于2.4内核的驱动,要知道编译的过程是有很大区别的呀,即使编译通过,也不能加载在板上运行的啊。编译移植 u-boot、编译内核,就这样曲曲折折走来,终于能看到点东西了,hello word 出来后,我的LED也很快就被我点亮了 ,更深层的东西还在继续……