Chinaunix首页 | 论坛 | 博客
  • 博客访问: 286067
  • 博文数量: 59
  • 博客积分: 1346
  • 博客等级: 中尉
  • 技术积分: 461
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-06 17:17
文章分类

全部博文(59)

文章存档

2012年(9)

2011年(50)

分类: LINUX

2011-01-11 13:31:54

 模块结构介绍

利用Linux设备驱动程序的第一个例程:Hello World模块了解内核驱动模块的结构。

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

static int hello_init(void)
{
    printk(KERN_ALERT "Hello, Tekkaman Ninja \n");
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_ALERT "Goodbye, Tekkaman Ninja \n Love Linux !Love ARM ! Love KeKe !\n");
}

module_init(hello_init);
module_exit(hello_exit);

 

MODULE_LICENSE("Dual BSD/GPL");

 

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

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

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

MODULE_LICENSE("Dual BSD/GPL");

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

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

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

3.   初始化和关闭

初始化的实际定义通常如下:

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

module_init(initialization_function)


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

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

module_exit(cleanup_function)

 4.   一个简单的Makefile文件:

KERNELDIR = /home/tekkaman/working/SBC2440/linux-2.6.22.2

PWD := $(shell pwd)

INSTALLDIR = /home/tekkaman/working/rootfs/lib/modules

CROSS_COMPILE    = arm-9tdmi-linux-gnu-

CC    = $(CROSS_COMPILE)gcc

obj-m := hello.o

.PHONY: modules modules_install clean

modules:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:

cp hello.ko $(INSTALLDIR)

clean:

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

obj-m := hello.o

代表了我们要构造的模块名为hell.komake 会在该目录下自动找到hell.c文件进行编译。如果 hello.o是由其他的源文件生成(比如file1.cfile2.c)的,则在下面加上(注意红色字体的对应关系):

hello-objs := file1.o file2.o ......

 

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

-C $(KERNELDIR) 指定了内核源代码的位置,其中保存有内核的顶层makefile文件。

M=$(PWD指定了模块源代码的位置

modules目标指向obj-m变量中设定的模块。

5.   编译模块

make  modules make  modules_install

[root@Tekkaman-Ninja Helloworld]# make modules
make -C /home/tekkaman/working/SBC2440/linux-2.6.22.2 M=/home/tekkaman/working/Linuxdriver/Helloworld modules
make[1]: Entering directory `/home/tekkaman/working/SBC2440/linux-2.6.22.2'
  CC [M]  /home/tekkaman/working/Linuxdriver/Helloworld/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/tekkaman/working/Linuxdriver/Helloworld/hello.mod.o
  LD [M]  /home/tekkaman/working/Linuxdriver/Helloworld/hello.ko
make[1]: Leaving directory `/home/tekkaman/working/SBC2440/linux-2.6.22.2'
[root@Tekkaman-Ninja Helloworld]# make modules_install
cp hello.ko /home/tekkaman/working/rootfs/lib/modules
[root@Tekkaman-Ninja Helloworld]#
 

6.   在开发板上的操作:

[Tekkaman2440@SBC2440V4]#cd /lib/modules/

[Tekkaman2440@SBC2440V4]#ls

cs89x0.ko hello.ko p80211.ko prism2_usb.ko 

[Tekkaman2440@SBC2440V4]#insmod hello.ko 

Hello, Tekkaman Ninja

[Tekkaman2440@SBC2440V4]#lsmod 

Module Size Used by Not tainted 

hello 1376 0 

[Tekkaman2440@SBC2440V4]#rmmod hello 

Goodbye, Tekkaman Ninja

Love Linux !Love ARM ! Love KeKe ! 

[Tekkaman2440@SBC2440V4]#lsmod 

Module Size Used by Not tainted 

[Tekkaman2440@SBC2440V4]#

 
 
另外一个例子
 
有三个文件,分别为hello.c add.c Makefile
hello.c文件
 
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Xie");
MODULE_DESCRIPTION("Hello World Module");
MODULE_ALIAS("a simplest module");
extern int add_integar(int a,int b);
extern int sub_integar(int a,int b);
static int __init hello_init()
{
    int res = add_integar(1,2);
    return 0;
}
static void __exit hello_exit()
{
    int res = sub_integar(2,1);

}
module_init(hello_init);
module_exit(hello_exit);
 
add.c文件
 
int add_integar(int a,int b)                               
{                               
 return a+b;                            
}
                              
int sub_integar(int a,int b)                               
{                               
 return a-b;                            
}                           
Makefile文件
 
ifneq ($(KERNELRELEASE),)
obj-m := main.o
main-objs:=hello.o add.o
else
 
KDIR := /lib/modules/2.6.35-24-generic/build
all:
 make -C $(KDIR) M=$(PWD) modules
clean:
 rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif
 
然后make,产生main.ko文件
insmod main.ko  加载文件
lsmod           查看加载成功
rmmod main      卸载文件
 
modprobe main,如同insmod一样,只是他会根据/lib/modules/<$version>modules.dep来连接某些它要依赖的文件。(make dep是连接依赖文件的意思)
 
 
二 模块参数
    module_param_array(name,type,num,perm);
   name 是你的数组的名子(也是参数名), type 是数组元素的类型, num 是一个整型变量, perm 是通常的权限值
例:
static char *whom = "world";
static int howmany = 1;
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);
在加载时可以直接修改参数,比如 sudo insmod hello.ko whom=hello,那么打印的信息就是hello而不是world了。
三 内核符号导出概念
EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);
name是指被调用的函数名

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