发布: 2009-8-15 12:26 | 作者: master | 查看: 0次
今天尝试了linux下的驱动开发,花了一个上午的时间终于在PC和ARM上跑成功了经典驱动教材《LINUX设备驱动程序》的第一个例子 hello.c。看似简单的程序折腾了我不少时间。<?XML:NAMESPACE PREFIX = O />
由于我用的redhat9.0,以及arm上以前烧录的是linux<?XML:NAMESPACE PREFIX = ST1 />2.4.20的内核因此只能用《LINUX设备驱动程序》第二板中的源代码,《LINUX设备驱动程序》第三版的源代码是for 2.6的内核的。2.4与2.6的驱动模型做了改动,因此开发的过程,有点不大一样,有兴趣的人可以自己在网上搜索看看。不过我也会简单比较一下不同点.
首先拿到hello.c的源代码:
Ldd2(《LINUX设备驱动程序》的简称)给的如下:
/*
* $Id: hello.c,v 1.10 2001/07/17 10:30:02 rubini Exp $
*/
#define MODULE
#include <linux/module.h>
/*
* These lines, although not shown in the book,
* are needed to make hello.c run properly even when
* your kernel has version support enabled
*/
int init_module(void) { printk("<1>Hello, world\n"); return 0; }
void cleanup_module(void) { printk("<1>Goodbye cruel world\n"); }
你会发现这个程序其实是有问题的:我做了简单修改:
/*
* $Id: hello.c,v 1.10 2001/07/17 10:30:02 rubini Exp $
*/
#define MODULE
#include <linux/module.h>
/*
* These lines, although not shown in the book,
* are needed to make hello.c run properly even when
* your kernel has version support enabled
*/
MODULE_LICENSE("GPL"); //添加这句话,否则在PC上编译的时候会出现
//警告,没有注册
//2.6的注册不同:
//MODULE_LICENSE("Dual BSD/GPL");
#include <linux/kernel.h> //添加了这个头文件printk函数在里面
int init_module(void) { printk("<1>Hello, world\n"); return 0; }
void cleanup_module(void) { printk("<1>Goodbye cruel world\n"); }
//2.6内核中这两个函数改成了
/*
static int hello_init(void)
{
printk(KERN_INFO " Hello World enter\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_INFO " Hello World exit\n ");
}
module_init(hello_init);
module_exit(hello_exit);
*/
程序修改好后就可以编译了:
#gcc –I /usr/src/linux2.4/include/linux –c hello.c
//说明:写内核或内核模块不能用写应用程序时的系统调用或函数库
// -I 后面是就是编译模块专用的内核库路径
//注意 这里编译驱动模块 只需编译到 *.o格式就可以了
编译好后我们执行:
#lsmod //看看现在有那些驱动在内核中
#insmod hello.o //加入我们刚刚编译的驱动
//这里可能会报linux版本不匹配的错误
解决方法:1.无视它 改用#insmod –f hello.o
2. 有人提供这样的建议:
进入/usr/include/linux/目录
把version.h第一句
#define UTS_RELEASE 2.4.20-1"
改成
#define UTS_RELEASE "2.4.20",这样就可以了。以你自己为准
这时候我们查看打印信息:printk函数相关内容与优先级这里不赘述,自己查看~
由于我们在xwindow下使用的是虚拟终端,所以终端不回打印,在这里查看:
#cat /var/log/messiges
发现已经有Hello, world输出了
接下来:
#rmmod hello //卸载驱动,注意不是hello.o
同样在messiges里有good bye输出了
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 分隔线
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
接下来我们交叉编译该文件,方法与上面一样
代码稍微修改一下,需要删除:
MODULE_LICENSE("GPL"); //这句话,否则交叉编译不过去,不明,达人指教下!!
然后我们编译:
/opt/host/armv4l/bin/armv4l-linux-gcc –D__KERNEL__-I /usr/src/linux-2.4/include/linux/ -DMODULE –c hello.c
// /opt/host/armv4l/bin/armv4l-linux-gcc我的交叉编译gcc
// –D__KERNEL__ -DMODULE 代表编译的是内核模块
// -I 同上
这时生成了hello.o,载到arm板子上,执行
#insmod –f hello.o //无视版本警告
//会直接输出打印信息 hello world 因为这不是虚拟终端
#rmmod hello //卸载 打印信息 goodbye
文章评论(0条评论)
登录后参与讨论