如何linux查看加载的模块Linux加载内置模块的信息

Posts - 61,
Articles - 3,
Comments - 387
&&&&&&&&&&&&&&&&——非淡泊無以明志,非寧靜無以致遠。
21:47 by Florian, ... 阅读,
Linux模块机制浅析
Linux允许用户通过插入模块,实现干预内核的目的。一直以来,对linux的模块机制都不够清晰,因此本文对内核模块的加载机制进行简单地分析。
模块的Hello World!
我们通过创建一个简单的模块进行测试。首先是源文件main.c和Makefile。
florian@florian-pc:~/module$ cat main.c
#include&linux/module.h&
#include&linux/init.h&
static int __init init(void)
&&& printk("Hi module!\n");
&&& return 0;
static void __exit exit(void)
&&& printk("Bye module!\n");
module_init(init);
module_exit(exit);
其中init为模块入口函数,在模块加载时被调用执行,exit为模块出口函数,在模块卸载被调用执行。
florian@florian-pc:~/module$ cat Makefile
obj-m += main.o
#generate the path
CURRENT_PATH:=$(shell pwd)
#the current kernel version number
LINUX_KERNEL:=$(shell uname -r)
#the absolute path
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
#complie object
&&& make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
&&& make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
其中,obj-m指定了目标文件的名称,文件名需要和源文件名相同(扩展名除外),以便于make自动推导。
然后使用make命令编译模块,得到模块文件main.ko。
florian@florian-pc:~/module$ make
make -C /usr/src/linux-headers-2.6.35-22-generic&M=/home/florian/module modules
make[1]: 正在进入目录 `/usr/src/linux-headers-2.6.35-22-generic'
& Building modules, stage 2.
& MODPOST 1 modules
make[1]:正在离开目录 `/usr/src/linux-headers-2.6.35-22-generic'
使用insmod和rmmod命令对模块进行加载和卸载操作,并使用dmesg打印内核日志。
florian@florian-pc:~/module$ sudo insmod main.dmesg | tail -1
[] Hi module!
florian@florian-pc:~/module$ sudo rmmod main.dmesg | tail -1
[] Bye module!
通过内核日志信息,可以看出模块的入口函数和出口函数都被正确调用执行。
使用readelf命令查看一下模块文件main.ko的信息。
florian@florian-pc:~/module$ readelf -h main.ko
ELF Header:
& Magic:&& 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
& Class:&&&&&&&&&&&&&&&&&&&&&&&&&&&& ELF32
& Data:&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 2's complement, little endian
& Version:&&&&&&&&&&&&&&&&&&&&&&&&&& 1 (current)
& OS/ABI:&&&&&&&&&&&&&&&&&&&&&&&&&&& UNIX - System V
& ABI Version:&&&&&&&&&&&&&&&&&&&&&& 0
& Type:&&&&&&&&&&&&&&&&&&&&&&&&&&&&& REL (Relocatable file)
& Machine:&&&&&&&&&&&&&&&&&&&&&&&&&& Intel 80386
& Version:&&&&&&&&&&&&&&&&&&&&&&&&&& 0x1
& Entry point address:&&&&&&&&&&&&&& 0x0
& Start of program headers:&&&&&&&&& 0 (bytes into file)
& Start of section headers:&&&&&&&&& 1120 (bytes into file)
& Flags:&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0x0
& Size of this header:&&&&&&&&&&&&&& 52 (bytes)
& Size of program headers:&&&&&&&&&& 0 (bytes)
& Number of program headers:&&&&&&&& 0
& Size of section headers:&&&&&&&&&& 40 (bytes)
& Number of section headers:&&&&&&&& 19
& Section header string table index: 16
我们发现main.ko的文件类型为可重定位目标文件,这和一般的目标文件格式没有任何区别。我们知道,目标文件是不能直接执行的,它需要经过链接器的地址空间分配、符号解析和重定位的过程,转化为可执行文件才能执行。
那么,内核将main.ko加载后,是否对其进行了链接呢?
模块数据结构
首先,我们了解一下模块的内核数据结构。
linux3.5.2/kernel/module.h:220
struct module
&&& ……
&&& /* Startup function. */
&&& int (*init)(void);
&&& ……
&&& /* Destruction function. */
&&& void (*exit)(void);
&&& ……
模块数据结构的init和exit函数指针记录了我们定义的模块入口函数和出口函数。
模块加载由内核的系统调用init_module完成。
linux3.5.2/kernel/module.c:3009
/* This is where the real work happens */
SYSCALL_DEFINE3(init_module, void __user *, umod,
&&&&&& unsigned long, len, const char __user *, uargs)
&&& struct module *
&&& int ret = 0;
&&& ……
&&& /* Do all the hard work */
&&& mod = load_module(umod, len, uargs);//模块加载
&&& ……
&&& /* Start the module */
&&& if (mod-&init != NULL)
&&&&&& ret = do_one_initcall(mod-&init);//模块init函数调用
&&& ……
&&& return 0;
系统调用init_module由SYSCALL_DEFINE3(init_module...)实现,其中有两个关键的函数调用。load_module用于模块加载,do_one_initcall用于回调模块的init函数。
函数load_module的实现为。
linux3.5.2/kernel/module.c:2864
/* Allocate and load the module: note that size of section 0 is always
&& zero, and we rely on this for optional sections. */
static struct module *load_module(void __user *umod,
&&&&&&&&&&&&& & unsigned long len,
&&&&&&&&&&&&& & const char __user *uargs)
&&& struct load_info info = { NULL, };
&&& struct module *
&&& ……
&&& /* Copy in the blobs from userspace, check they are vaguely sane. */
&&& err = copy_and_check(&info, umod, len, uargs);//拷贝到内核
&&& if (err)
&&&&&& return ERR_PTR(err);
&&& /* Figure out module layout, and allocate all the memory. */
&&& mod = layout_and_allocate(&info);//地址空间分配
&&& if (IS_ERR(mod)) {
&&&&&& err = PTR_ERR(mod);
&&&&&& goto free_
&&& ……
&&& /* Fix up syms, so that st_value is a pointer to location. */
&&& err = simplify_symbols(mod, &info);//符号解析
&&& if (err & 0)
&&&&&& goto free_
&&& err = apply_relocations(mod, &info);//重定位
&&& if (err & 0)
&&&&&& goto free_
&&& ……
函数load_module内有四个关键的函数调用。copy_and_check将模块从用户空间拷贝到内核空间,layout_and_allocate为模块进行地址空间分配,simplify_symbols为模块进行符号解析,apply_relocations为模块进行重定位。
由此可见,模块加载时,内核为模块文件main.ko进行了链接的过程!
至于函数do_one_initcall的实现就比较简单了。
linux3.5.2/kernel/init.c:673
int __init_or_module do_one_initcall(initcall_t fn)
&&& int count = preempt_count();
&&& if (initcall_debug)
&&&&&& ret = do_one_initcall_debug(fn);
&&&&&& ret = fn();//调用init module
&&& ……
即调用了模块的入口函数init。
模块卸载由内核的系统调用delete_module完成。
linux3.5.2/kernel/module.c:768
SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
&&& &&& unsigned int, flags)
&&& struct module *
&&& char name[MODULE_NAME_LEN];
&&& int ret, forced = 0;
&&& ……
&&& /* Final destruction now no one is using it. */
&&& if (mod-&exit != NULL)
&&&&&& mod-&exit();//调用exit module
&&& ……
&&& free_module(mod);//卸载模块
&&& ……
通过回调exit完成模块的出口函数功能,最后调用free_module将模块卸载。
如此看来,内核模块其实并不神秘。传统的用户程序需要编译为可执行程序才能执行,而模块程序只需要编译为目标文件的形式便可以加载到内核,有内核实现模块的链接,将之转化为可执行代码。同时,在内核加载和卸载的过程中,会通过函数回调用户定义的模块入口函数和模块出口函数,实现相应的功能。参考资料以上由提供
当前位置:
> 详细页面
如何查看Linux加载内置模块的信息
时间: 16:16来源:作者:zhijie
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
系统教程栏目
热门系统教程
在笔记本电脑早已普及到会议室的这个年代,商务人士拿笔记...
热门系统下载
最新系统教程
热门软件下载
Copyright&2011 系统之家(www.xitongzhijia.net) 版权所有 闽ICP备号-1
本站发布的系统与软件仅为个人学习测试使用,请在下载后24小时内删除,不得用于任何商业用途,否则后果自负,请支持购买微软正版软件!
如侵犯到您的权益,请及时通知我们,我们会及时处理。查看Apache加载的模块
查看Apache加载的模块
.apachectl -t -D DUMP_MODULES
apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
Loaded Modules:
&core_module (static)
&log_config_module (static)
&logio_module (static)
&mpm_prefork_module (static)
&http_module (static)
&so_module (static)
&alias_module (shared)
&auth_basic_module (shared)
&authn_file_module (shared)
&authz_default_module (shared)
&authz_groupfile_module (shared)
&authz_host_module (shared)
&authz_user_module (shared)
&autoindex_module (shared)
&cgi_module (shared)
&deflate_module (shared)
&dir_module (shared)
&env_module (shared)
&mime_module (shared)
&negotiation_module (shared)
&php5_module (shared)
&proxy_module (shared)
&proxy_http_module (shared)
&reqtimeout_module (shared)
&setenvif_module (shared)
&status_module (shared)
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'中国领先的IT技术网站
51CTO旗下网站
如何找出Linux系统中内置模块的信息
最新的Linux发行版的内核只带了相对较小的“内置模块(built-in modules)”,其余的特定硬件驱动或者自定义功能作为“可加载模块”来让你有选择地加载或卸载。我想要知道Linux系统中内核内置的模块,以及每个模块有哪些参数。有什么方法可以得到内置模块和设备驱动的列表,以及它们的详细信息呢?
作者:Dan Nanni来源:| 14:56
提问:我想要知道Linux系统中内核内置的模块,以及每个模块有哪些参数。有什么方法可以得到内置模块和设备驱动的列表,以及它们的详细信息呢?
现代Linux内核正在随着时间变化而迅速增长,以支持大量的硬件、文件系统和网络功能。在此期间,&可加载模块(loadable kernel
modules,[LKM])&的引入防止内核变得越来越臃肿,以及在不同的环境中灵活地扩展功能及硬件支持,而不必重新构建内核。
最新的Linux发行版的内核只带了相对较小的&内置模块(built-in modules)&,其余的特定硬件驱动或者自定义功能作为&可加载模块&来让你有选择地加载或卸载。
内置模块被静态地编译进了内核。不像可加载内核模块可以动态地使用modprobe、insmod、rmmod、modinfo或者lsmod等命令地加载、卸载、查询模块,内置的模块总是在启动时就加载进了内核,不会被这些命令管理。
找出内置模块列表
要得到内置模块列表,运行下面的命令。
$ cat /lib/modules/$(uname -r)/modules.builtin
你也可以用下面的命令来查看有哪些内置模块:
找出内置模块参数
每个内核模块无论是内置的还是可加载的都有一系列的参数。对于可加载模块,modinfo命令可以显示它们的参数信息。然而这个命令对内置模块没有用。你会得到下面的错误。
modinfo: ERROR: Module XXXXXX not found.
如果你想要查看内置模块的参数,以及它们的值,你可以在 /sys/module 下检查它们的内容。
在 /sys/module目录下,你可以找到内核模块(包含内置和可加载的)命名的子目录。进入每个模块目录,这里有个&parameters&目录,列出了这个模块所有的参数。
比如你要找出tcp_cubic(内核默认的TCP实现)模块的参数。你可以这么做:
$ ls /sys/module/tcp_cubic/parameters
接着阅读这个文件查看每个参数的值。
$ cat /sys/module/tcp_cubic/parameters/tcp_friendliness
作者: 译者: 校对:
原创编译, 荣誉推出【编辑推荐】【责任编辑: TEL:(010)】
大家都在看猜你喜欢
头条头条外电头条头条
24H热文一周话题本月最赞
讲师:5人学习过
讲师:34人学习过
讲师:5人学习过
精选博文论坛热帖下载排行
本书重点讲解如何用实用的代码来解决具体的实际问题。本书的内容覆盖面很广,从新的C#范型到Web服务,从反射到安全等都有涉及。系统地介绍...
订阅51CTO邮刊linux(82)
android(80)
驱动操作命令:
&&&&& insmod / modprobe 加载驱动
&&&&& rmmod&&&&&&&&&&&&&&&&&&&& 卸载驱动
&&&&& lsmod&&&&&&&&&&&&&&&&&&&&&&&查看系统中所有已经被加载了的所有的模块以及模块间的依赖关系
&&&&&&modinfo&&&&&&&&&&&&&&&&&&& 获得模块的信息
查看已经加载的驱动模块的信息:
&&&lsmod&&&能够显示驱动的大小以及被谁使用&&
&& &cat /proc/modules&&& 能够显示驱动模块大小、在内核空间中的地址
&&&&& cat /proc/devices&&& 只显示驱动的主设备号,且是分类显示&
&&&&& /sys/modules&&&&&&&&& 下面存在对应的驱动的目录,目录下包含驱动的分段信息等等。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:266169次
积分:3790
积分:3790
排名:第5756名
原创:43篇
转载:464篇
评论:58条
(3)(1)(2)(3)(2)(7)(8)(12)(9)(7)(4)(3)(14)(2)(23)(6)(17)(5)(2)(1)(1)(4)(4)(22)(38)(34)(2)(45)(3)(1)(5)(1)(3)(19)(13)(21)(10)(13)(3)(11)(40)(22)(16)(2)(8)(12)(4)(2)(7)(1)(3)(3)(2)(1)

我要回帖

更多关于 linux加载驱动模块 的文章

 

随机推荐