免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2718 | 回复: 1
打印 上一主题 下一主题

模块开发者肘边书v0.2 --话说排版真是个大问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-08-02 17:53 |只看该作者 |倒序浏览
本帖最后由 gzg1984 于 2011-09-05 17:21 编辑

gzg1984@yahoo.com.cn

qq:709581191

1
一个最简单的模块代码文件是什么样子?

/* variable.c*/

long module_variable;

虽然可能和你之前所想的不同,但是这一行代码确实可以被编译成模块。

与之相配的最简单的模块Makefile是这样的:

obj-m
:=variable.o

default:


make-C /lib/modules/$(shell uname -r)/build
M=$(shell pwd) modules

2
为毛我没有看见模块的初始化函数或者头文件之类的东西?没有这些东西真的没问题吗?这个模块可以执行吗?

因为那些东西不是“模块”的必须组件,当然,一个带有实际功能的模块,一般应该有初始化函数和退出函数。

被标记为module_init的函数会在模块加载时运行。但是模块并不是真的必须包含一个module_init函数。

另外:你始终要记住一点,模块不能“执行”,甚至不能“调用”。加载模块的的过程,不是“执行模块”,也不是“调用模块”,而是将模块代码“加载”到内核代码空间中。

Module_init标记的入口函数,会由insmod进程在完成模块“加载”工作之后进行“调用”。module_init函数的执行过程可以被称为模块“加载”过程中的一个步骤,但并不是唯一的步骤,也不是最重要的步骤,甚至不是必须经过的步骤。

3
如果我什么头文件都不带,那为什么在modinfo中还可以看到vermagic值?

那是因为模块的vermagic值不是记录在你写的模块源代码中。

在编译完成上面的模块例子之后,你应该可以看到这个目录下多出了一个variable.mod.c 文件。这个文件会和你写的源代码variable.c编译到一起,构成variable.ko

Vermagic的值,是通过variable.mod.c文件引入variable.ko的。

4
那么这个最简单的模块有什么用吗?

一点用也没有。

内核中的其他代码也无法访问到这个变量。

5
一个有一点用处的最简单的模块应该是什么样子?

/* variable.c*/

static long module_variable;

EXPORT_SYMBOL(module_variable);

Makefile不变。

这样一个模块,应该无法被内核已经有的模块使用,但是却可以为你以后写的所有模块提供一个公用的变量。当然,如果你真打算把它当做模块间同步的工具,你还应该为它设计一个锁。

6
导出和static修饰不冲突吗?

导出和”static”概念有区别:

1static在内核中的含义也只是限定一个变量只有本文件可以使用。

2Static限制的变量也可以导出。

3:所有导出了的变量名都是唯一的。

4:只要导出了的变量就可以在其他模块使用,无论次变量是否static修饰。

5:一个变量或函数能不能由本模块中的其他文件使用,是由static修饰决定,规则与普通C语言规则一样,无论此函数是否导出。

总结地说,static的限制范围作用于模块本身以及模块自己的编译过程。导出的作用范围是模块加载入内核后的内核符号表。

7
一个带有函数的最简单的模块是什么样子?

#include <linux/module.h>

static int test1(void)

{


printk("it's test1 .\n");


return 0;

}

EXPORT_SYMBOL(test1);

这不再是一个完全没用的例子了。你可以写一个新的模块来调用test1函数。

8
已经导出的函数怎么使用?

可以直接调用。当然,需要先声明原型。

但是注意,如果你的模块里面也有一个test1,那么你会调用到你自己模块里的test1而不是其他模块导出的test1.

9
我怎么知道谁导出了什么函数?

/proc/kallsyms文件中有内核代码空间中所有的函数,格式是这样的:

f7c42254
t
find_nls
[nls_base]

f7c42073
T
utf32_to_utf8
[nls_base]

中间的t代表没有导出,T代表导出的函数。

10
模块参数的用法

int value = 5;

char *s = "hello dog";

module_param(value, int, S_IWUSR |S_IRUGO);

module_param(s, charp, S_IWUSR | S_IRUGO);

以上就声明了两个模块函数,可以在加载模块时使用value=X之类的方法设置这些置。不设置的话,这些变量保存的就是默认值。Module_param的第三个参数是指的这个参数对应的/sys目录下的文件的访问权限。所有模块参数都会各自被抽象成一个文件,存放在/sys/modules目录下面。这里的module_param的第三个参数,就是约束那个文件的访问权限的。

11
模块参数数组的用法

static unsigned int many[5] = {1, 2, 3, 4,5};

static int num = 20;

module_param_array(many, uint, &num,0444);

将以上代码加入到模块代码中,就可以使用模块参数数组了。

模块参数数组的大小,模块代码会自己去计算,和第三参数num没有关系。

Num的作用是记录传入参数的个数。

传入参数的办法:

insmod param_array.ko many=1,3,5,7

这样可以将many数组的前4个值修改为1,3,5,7,但是第5个值没有变化。

Num的值会变成4

12
内核污染问题

当新加载的模块未声明许可证或者许可证不被内核认可的时候,内核将输出kernel tainted警告。这种情况,一般被称为内核污染。

声明许可证的方法:

MODULE_LICENSE(“licensename”)

声明许可证的举例

MODULE_LICENSE("Dual BSD/GPL");

MODULE_LICENSE("GPL");

MODULE_LICENSE("BSD ");

13
符号导出问题

导出方法有以下两种

EXPORT_SYMBOL

EXPORT_SYMBOL_GPL

导出的“符号”可以是变量,也可以是函数,但是主要功能是导出函数。

在最新版的内核中使用这种办法导出变量,在编译过程中会产生警告

14
模块版本问题

CONFIG_MODVERSIONS内核选项打开后,加载模块时,内核将会强制验证模块的版本,如果和内核版本不一致,内核会拒绝加载。

模块的内核版本记录在于模块一起编译的.mod.c文件中,一般形式如下:

MODULE_INFO(vermagic, VERMAGIC_STRING);

v2.6.34.8menuconfig中只有version检查的选项,

但是(不知道是内核升级还是发布版定制导致),后续还出现了校验内核接口CRC的版本校验,导致即使同一个小版本号的内核,只要源码树不同,编译出的模块就可能无法互通。

解决办法:

1:模块与内核在同一个目录树下编译

2:解除内核的版本检查机制。

15
自动drop的代码段

当一个函数被标注为__init的时候,它将被加载并使用一次,然后保存其代码的内存将被释放。这是一个半自动的过程:编程者指定哪些代码只用一次,而内核按照编程者的指定丢弃使用过的代码。

一般模块加载时的入口函数会被标记为__init。这个函数与模块中其他函数的不同就在于:其他函数将被加载进内核的代码空间中,直到卸载模块为止;而这个“初始化函数”,开始时也会被加载进内核的代码空间中,但是内核在调用过一次后,就会将这段代码自动自动丢弃掉,内核的代码空间中再也看不见这个函数了。


论坛徽章:
0
2 [报告]
发表于 2011-08-03 10:18 |只看该作者
不错,学习了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP