linux驱动开发

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

View Code
复制代码
 1 #include <linux/init.h>
2 #include <linux/module.h>
3
4 static int __init hello_init(void)
5 {
6 printk(KERN_ALERT"Hello World\n");
7 return 0;
8 }
9
10 static void __exit hello_exit(void)
11 {
12 printk(KERN_ALERT"Goodbye, cruel world\n");
13 }
14
15 module_init(hello_init);
16 module_exit(hello_exit);
17
18 MODULE_LICENSE("GPL");
复制代码

 

1 #include <linux/init.h>
2 #include <linux/module.h>
3
4 static int __init hello_init(void)
5 {
6 printk(KERN_ALERT"Hello World\n");
7 return 0;
8 }
9
10 static void __exit hello_exit(void)
11 {
12 printk(KERN_ALERT"Goodbye, cruel world\n");
13 }
14
15 module_init(hello_init);
16 module_exit(hello_exit);
17
18 MODULE_LICENSE("GPL");

1、 所有模块都包含以下两个头文件:

View Code
1 #include <linux/init.h>
2 #include <linux/module.h>
#include <linux/init.h>
2 #include <linux/module.h>

module.h包含有可装载模块所需要的大量符号和函数定义。

包含init.h的目的是指定初始化和清除函数。

 

2、尽管不是严格要求,但模块应该指定代码所使用的许可证。

View Code
1 MODULE_LICENSE("GPL");

 

1 MODULE_LICENSE("GPL");

内核能够识别的许可证有:

View Code
1 “GPL”(任一版本的GNU通用公共许可证)
2 “GPL v2”(GPL版本2)
3 “GPL and additional rights”(GPL及附加权利)
4 “Dual BSD/GPL”(BSD/GPL双重许可证)
5 “Dual MPL/GPL”(MPL/GPL双重许可证)
6 “Proprietary”(专有)
1 “GPL”(任一版本的GNU通用公共许可证)
2 “GPL v2”(GPL版本2)
3 “GPL and additional rights”(GPL及附加权利)
4 “Dual BSD/GPL”(BSD/GPL双重许可证)
5 “Dual MPL/GPL”(MPL/GPL双重许可证)
6 “Proprietary”(专有)

如果一个模块没有显示地标记为上述内核可识别的许可证,则会被假定是专有的,而内核装载这种模块就会被“污染”。

 

另外,可在内核中包含其他描述性定义:

View Code
1 MODULE_AUTHOR(); (描述模块作者)
2 MODULE_DESCRIPTION(); (说明模块用途)
3 MODULE_VERSION(); (代码修订号)
4 MODULE_ALIAS(); (模块别名)
5 MODULE_DEVICE_TABLE(); (用来告诉用户空间模块所支持的设备)

上述MODULE_声明可出现在源文件中源代码函数以外的任何地方,新近的内核编码习惯是将这些声明放在文件的最后

 

3、初始化和关闭

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

View Code
1 static int __init initialization_function(void)
2 {
3 /* 这里是初始化代码 */
4 }
5 module_init(initialization_function);

__init和__initdata表明该函数仅在初始化期间使用。

__devinit和__devinitdata,只有在内核未被配置为支持可热插拔设备的情况下,才会被翻译为__init和__initdata

 

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

View Code
1 static void __exit cleanup_function(void)
2 {
3 /* 这里是清除代码 */
4 }
5 module_exit(cleanup_function);

被标记为__exit的函数只能在模块被卸载或者系统关闭时被调用。

如果一个模块未定义清除函数,则内核不允许卸载该模块。

 

4、Makefile分析

View Code

obj-:= hello.o

代表了我们要构造的模块名称为hello.ko,make会在当前目录下找到hello.c文件进行编译。如果hello.o是由两个源文件生成(比如file1.c和file2.c),则正确的makefile可如下编写:

obj-:= hello.o

hello-objs := file1.o file2.o

make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-

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

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

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

 

insmod hello.ko

dmesg

转载于:https://www.cnblogs.com/nuistlr/archive/2012/06/20/2556993.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值