Chinaunix首页 | 论坛 | 博客
  • 博客访问: 268340
  • 博文数量: 74
  • 博客积分: 1336
  • 博客等级: 中尉
  • 技术积分: 1057
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-02 09:33
文章分类

全部博文(74)

文章存档

2016年(6)

2015年(4)

2014年(20)

2013年(8)

2012年(16)

2010年(9)

2009年(11)

我的朋友

分类: LINUX

2010-02-15 20:04:02

Linux设备驱动程序的第一个例程:

/*                                                    

 * $Id: hello.c,v 1.5 2004/10/26 03:32:21 corbet Exp $

 */                                                   

#include

#include

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void)

{

     printk("Hello, world\n");

     return 0;

}

static void hello_exit(void)

{

     printk("Goodbye, cruel world\n");

}

module_init(hello_init);

module_exit(hello_exit);


我将其复制到我的工作目录,并编写了一个简单的Makefile文件:

obj-m  :=hello.o

CROSS_COMPILE    = arm-linux-

CC    = $(CROSS_COMPILE)gcc

KDIR   :=/work/kernel/linux-2.6.14

#KDIR :=/lib/modules/2.6.21-1.3194.fc7/build

PWD   :=$(shell pwd)

 

default:

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

clean:

     rm -rf *.o* *~ core .depend .*.cmd *.ko *.mod.c

     rm -rf .tmp_versions/

install:

     cp *.ko /work/rootfile/rootfs/lib/modules/2.6.14/


在我的开发板上的操作:

[root@NEU/]# insmod /lib/modules/2.6.14/hello.ko

Hello, world

[root@NEU/]# lsmod

hello 1024 0 - Live 0xbf000000

[root@NEU/]# rmmod hello

Goodbye, world

[root@NEU/]# lsmod

[root@NEU/]#

 


学习心得:
1)驱动模块运行在内核空间,运行时不能依赖于用户空间的任何函数库和模块连接,所以在写驱动时所调用的函数只能是作为内核一部分的函数,或者说只能调用内核的API函数
2)驱动模块和应用程序的一个重要不同是:应用程序退出时可不管资源释放或者其他的清除工作,但模块的退出函数必须仔细撤销初始化函数所作的一切,否则,在系统重新引导之前某些东西就会残留在系统中。
3)处理器的多种工作模式(级别)其实就是为了操作系统的用户空间和内核空间设计的。在Unix类的操作系统中只用到了两个级别:最高和最低级别。
4)要十分注意驱动程序的并发处理。
5)内核API中具有双下划线(_ _)的函数,通常是接口的底层组件,应慎用。
6)内核代码不能实现浮点数运算。
7Makefile文件分析:
obj-m := hello.
代表了我们要构造的模块名为hello.komake 会在该目录下自动找到hello.c文件进行编译。

如果 hello.o是由其他的源文件生成(比如file1.cfile2.c)的,则在下面加上(注意红色字体的对应关系):
hello-objs := file1.o file2.o ......

    $(MAKE) -C $(KDIR) M=$(PWD)
modules
其中 -C $(KDIR) 指定了内核源代码的位置,其中保存有内核的顶层makefile文件。而且zImage一定要编译出来,否则编译模块化得驱动的时候会有错误。
   
M=$(PWD指定了模块源代码的位置

8)所有模块代码中都包含一下两个头文件:

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


9)所有模块代码都应该指定所使用的许可证:

MODULE_LICENSE("Dual BSD/GPL");


此外还有可选的其他描述性定义:

MODULE_AUTHOR("");
MODULE_DESCRIPTION
("");
MODULE_VERSION
("");
MODULE_ALIAS
("");
MODULE_DEVICE_TABLE
("");


上述MODULE_声明习惯上放在文件最后。

10)初始化和关闭
初始化的实际定义通常如下:

static int _ _init initialization_function(void)
{
/*初始化代码*/
}
module_init
(initialization_function)


清除函数的实际定义通常如下:

static int _ _exit cleanup_function(void)
{
/*清除代码*/
}
module_exit
(cleanup_function)


11)模块参数:内核允许对驱动程序指定参数,而这些参数可在装载驱动程序模块时改变

问题集锦:

1、             makefileobj-m这个是关键字,小写 ,注意。CC大写,CROSS_COMPILE

大写。

2、             makefiledefaultcleaninstall:下面的命令行前面是tab空格,modules和前面的pwd之间也应该有个space空格

3、             内核代码目录里面,即KDIR里面,arch/arm/boot里面应该有zImage文件,并且在Makefile里面指定的cross_compile应该和你的编译驱动hello.c的编译器版本一致。

 

文件: 1.rar
大小: 0KB
下载: 下载

阅读(588) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~