linux module简介

本文介绍了Linux模块,自2.0版本起支持模块化,按需加载可使内核保持小体积,还能动态加载、卸载。阐述了模块的编写,需定义MODULE并包含特定头文件,编译有选项要求。说明了安装和移除模块的命令,如insmod、rmmod等,还给出了示例代码和Makefile。

Linux modules:
简介:
 linux 2.0版本以后都支持模块化,因为内核中的一部分常驻在内存中,(如最常使用的进程,如scheduler等),但是其它的进程只是在需要的时候才被载入。如MS-DOS文件系统只有当mount此类系统的时候才需要,这种按需加载,就是模块。它能使内核保持较小的体积,虽然可以把所有的东东都放在内核中,这样的话,我们就不需要模块了,但是这样通常是有特殊的用途(所有要运行的进程都预先知道的情况)。
 模块另一个优点是内核可以动态的加载、卸载它们(或者自动地由kerneld守护程序完成)。

Writing, Installing, and Removing Modules

WRiting Modules:
 除了它们运行在内核空间中之外,模块与其它程序类似。所以,必须定义MODULE并且包含头文件module.h以及其它的一些内核头文件。模块即可以很简单也可以很复杂。

一般的模块格式如下:

#define MODULE
#include <linux/module.h>
/*... other required header files... */

/*
 * ... module declarations and functions ...
 */

int
init_module()
{
 /* code kernel will call when installing module */
}

void
cleanup_module()
{
 /* code kernel will call when removing module */
}

使用内核源码的模块在用gcc编译时,必须使用如下的选项:
-I/usr/src/linux/include

注意并不是所有内核中的变量都被导出供模块使用的,即使代码中用extern声明了。在/proc/ksyms文件或者程序ksyms中显示了被导出的符号。现在的linux内核使用使用EXPORT_SYMBOL(x)宏来不仅导出符号,而且也导出版本号(version number)。如果是用户自己定义的变量,使用EXPORT_SYMBOL_NOVERS(x)宏。否则的话linker不会在kernel symbol table中保留此变量。可以使用EXPORT_NO_SYMBOLS宏不导出变量,缺省情况是模块导出所有的变量。

Installing and Removing Modules:
 必须是超级用户才可以的。使用insmod来安装一个模块:
  /sbin/insmod module_name
 rmmod命令移除一个已经安装了的模块,以及任何此模块所导出的引用。
  /sbin/rmmod module_name
 使用lsmod列出所有安装了的模块。

Example:
 simple_module.c

/* simple_module.c
 *
 * This program provides an example of how to install a trivial module
 *  into the Linux kernel. All the module does is put a message into
 *  the log file when it is installed and removed.
 *
 */


#define MODULE
#include <linux/module.h>
/* kernel.h contains the printk function */
#include <linux/kernel.h>

/* init_module
 * kernel calls this function when it loads the module
 */
int
init_module()
{
 printk("<1>The simple module installed itself properly./n");
 return 0;
} /* init_module */

/* cleanup_module
 * the kernel calls this function when it removes the module
 */
void
cleanup_moudle()
{
 printk("<1>The simple module is now uninstalled./n");
} /* cleanup_module */

This is the Makefile:

# Makefile for simple_module

CC=gcc -I/usr/src/linux/include/config
CFLAGS=-O2 -D__KERNEL__ -Wall

simple_module.o : simple_module.c

install:
 /sbin/insmod simple_module

remove:
 /sbin/rmmod simple_module

### 关于Linux内核模块开发与故障排除 #### Linux内核模块的基础概念 Linux内核模块是一种动态加载到运行中的内核中的代码片段,用于扩展内核的功能而不需重新编译整个内核。这些模块可以提供设备驱动程序、文件系统支持或其他功能[^2]。 当UEFI安全启动被启用时,Linux内核可能会禁止使用UIO(Userspace I/O),因此建议将DPDK使用的设备绑定到`vfio-pci`内核模块而不是任何基于UIO的模块[^1]。这有助于确保系统的安全性以及兼容性。 #### 开发流程概述 编写一个简单的内核模块通常涉及以下几个方面: - **初始化函数**:定义模块加载时执行的操作。 - **清理函数**:指定卸载模块时要完成的任务。 - 使用宏`module_init()`注册初始化函数,用`module_exit()`声明退出函数。 下面是一个基本的例子展示如何创建一个最基础的hello world类型的内核模块: ```c #include <linux/module.h> /* 所有模块都需要 */ #include <linux/kernel.h> /* KERN_INFO 宏 */ static int __init hello_start(void){ printk(KERN_INFO "Loading Hello module...\n"); return 0; // 非零返回表示失败,模块无法加载 } static void __exit hello_end(void){ printk(KERN_INFO "Goodbye Mr.\n"); } module_init(hello_start); module_exit(hello_end); MODULE_LICENSE("GPL"); // 设置许可证为GPL ``` #### 常见问题排查方法 如果遇到错误或者异常行为,在调试过程中可考虑以下几点: - 查看dmesg日志获取更多信息; - 确认依赖项已正确定义并存在; - 如果涉及到硬件访问,则注意权限设置及隔离策略的影响,比如前面提到的安全引导限制情况下的VFIO应用。 另外需要注意的是,虽然NAPI机制增强了多核环境下的性能表现[^4],但在某些特定场景下也可能暴露出其自身的不足之处,所以在设计高性能网络应用程序时应综合考量各种因素。 #### 参考资料关联说明 上述讨论涵盖了从基础知识介绍到实际编码实践再到潜在障碍克服等多个层面的内容,并适当引用了相关参考资料来增强论述的专业性和权威度。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值