当前位置: 首页 > article >正文

Linux内核中的模块化编程详解

Linux内核中的模块化编程详解引言模块化编程是Linux内核的一个重要特性它允许内核功能在运行时动态加载和卸载提高了内核的灵活性和可扩展性。Linux内核模块可以独立编译和加载不需要重新编译整个内核大大简化了内核开发和调试。本文将深入探讨Linux内核中的模块化编程包括其设计原理、开发方法、核心机制和应用场景。内核模块的基本概念1. 什么是内核模块内核模块是一种可以在运行时动态加载和卸载的内核代码它可以扩展内核的功能而不需要重新编译整个内核。2. 内核模块的优点灵活性可以动态加载和卸载模块可扩展性可以轻松扩展内核功能节省内存只在需要时加载模块便于开发模块可以独立开发和测试调试方便模块可以快速重新加载3. 内核模块的分类设备驱动模块控制硬件设备文件系统模块实现文件系统网络协议模块实现网络协议系统调用模块添加系统调用其他模块其他功能模块内核模块的结构1. 模块的基本结构一个简单的内核模块通常包含以下部分#include linux/module.h #include linux/kernel.h #include linux/init.h // 模块初始化函数 static int __init mymodule_init(void) { printk(KERN_INFO mymodule: init\n); return 0; } // 模块退出函数 static void __exit mymodule_exit(void) { printk(KERN_INFO mymodule: exit\n); } // 注册初始化函数 module_init(mymodule_init); // 注册退出函数 module_exit(mymodule_exit); // 模块许可证 MODULE_LICENSE(GPL); // 模块作者 MODULE_AUTHOR(Your Name); // 模块描述 MODULE_DESCRIPTION(A simple kernel module); // 模块版本 MODULE_VERSION(0.1);2. 模块初始化函数模块初始化函数在模块加载时执行。static int __init mymodule_init(void) { // 初始化代码 // ... return 0; // 成功 // 或者 // return -EINVAL; // 失败 }__init宏标记初始化函数返回值0表示成功负值表示失败3. 模块退出函数模块退出函数在模块卸载时执行。static void __exit mymodule_exit(void) { // 清理代码 // ... }__exit宏标记退出函数无返回值4. 模块声明宏// 模块许可证 MODULE_LICENSE(GPL); MODULE_LICENSE(GPL v2); MODULE_LICENSE(Dual BSD/GPL); MODULE_LICENSE(Proprietary); // 模块作者 MODULE_AUTHOR(Your Name); // 模块描述 MODULE_DESCRIPTION(Description of the module); // 模块版本 MODULE_VERSION(1.0); // 模块别名 MODULE_ALIAS(alias_name); // 模块设备表 MODULE_DEVICE_TABLE(platform, my_device_ids);内核模块的编译1. Makefile编译内核模块需要一个Makefile。obj-m mymodule.o all: make -C /lib/modules/$(shell uname -r)/build M$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M$(PWD) clean2. 编译模块# 编译模块 make # 清理模块 make clean3. 模块文件编译后会生成.ko文件这就是内核模块文件。mymodule.ko内核模块的加载和卸载1. 加载模块# 使用insmod加载模块 insmod mymodule.ko # 使用modprobe加载模块 modprobe mymodule # 带参数加载模块 insmod mymodule.ko param1value1 param2value22. 查看已加载模块# 查看所有已加载模块 lsmod # 查看特定模块 lsmod | grep mymodule # 查看模块信息 modinfo mymodule.ko3. 卸载模块# 使用rmmod卸载模块 rmmod mymodule # 使用modprobe卸载模块 modprobe -r mymodule4. 查看模块日志# 查看内核日志 dmesg # 实时查看内核日志 dmesg -w # 查看系统日志 tail -f /var/log/messages tail -f /var/log/syslog模块参数1. 定义模块参数#include linux/module.h #include linux/moduleparam.h // 整数参数 static int my_int 0; module_param(my_int, int, S_IRUGO); MODULE_PARM_DESC(my_int, An integer parameter); // 布尔参数 static bool my_bool false; module_param(my_bool, bool, S_IRUGO); MODULE_PARM_DESC(my_bool, A boolean parameter); // 字符串参数 static char *my_string default; module_param(my_string, charp, S_IRUGO); MODULE_PARM_DESC(my_string, A string parameter); // 数组参数 static int my_array[5] {0, 0, 0, 0, 0}; static int arr_argc 0; module_param_array(my_array, int, arr_argc, S_IRUGO); MODULE_PARM_DESC(my_array, An integer array);2. 模块参数的权限// 权限定义 S_IRUGO // 用户、组、其他可读 S_IWUSR // 用户可写 S_IRUSR // 用户可读3. 使用模块参数# 加载模块时传递参数 insmod mymodule.ko my_int42 my_bool1 my_stringhello my_array1,2,3,4,5内核模块的符号导出1. 导出符号#include linux/module.h // 导出函数 void my_function(void) { // ... } EXPORT_SYMBOL(my_function); // 导出函数仅GPL模块可用 void my_gpl_function(void) { // ... } EXPORT_SYMBOL_GPL(my_gpl_function); // 导出变量 int my_variable 0; EXPORT_SYMBOL(my_variable);2. 使用导出的符号#include linux/module.h // 声明外部符号 extern void my_function(void); extern int my_variable; // 使用导出的符号 static int __init mymodule_init(void) { my_function(); my_variable 42; return 0; }内核模块的依赖关系1. 模块依赖模块可以依赖其他模块导出的符号。// 模块A void function_a(void) { // ... } EXPORT_SYMBOL(function_a); // 模块B依赖模块A extern void function_a(void); static int __init module_b_init(void) { function_a(); // 使用模块A的函数 return 0; }2. 查看模块依赖# 查看模块依赖 modinfo mymodule.ko # 自动处理依赖 modprobe mymodule3. 模块引用计数#include linux/module.h // 增加模块引用计数 try_module_get(THIS_MODULE); // 减少模块引用计数 module_put(THIS_MODULE);实际案例分析案例简单的内核模块#include linux/module.h #include linux/kernel.h #include linux/init.h // 模块参数 static int count 1; module_param(count, int, S_IRUGO); MODULE_PARM_DESC(count, Number of times to print message); static int __init mymodule_init(void) { int i; printk(KERN_INFO mymodule: init\n); printk(KERN_INFO mymodule: count %d\n, count); for (i 0; i count; i) { printk(KERN_INFO mymodule: message %d\n, i 1); } return 0; } static void __exit mymodule_exit(void) { printK(KERN_INFO mymodule: exit\n); } module_init(mymodule_init); module_exit(mymodule_exit); MODULE_LICENSE(GPL); MODULE_AUTHOR(Your Name); MODULE_DESCRIPTION(A simple kernel module with parameters); MODULE_VERSION(0.1);对应的Makefileobj-m mymodule.o all: make -C /lib/modules/$(shell uname -r)/build M$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M$(PWD) clean案例导出符号的模块// module_a.c - 导出符号的模块 #include linux/module.h #include linux/kernel.h #include linux/init.h // 导出函数 void my_greeting(const char *name) { printk(KERN_INFO module_a: Hello, %s!\n, name); } EXPORT_SYMBOL(my_greeting); // 导出变量 int my_value 42; EXPORT_SYMBOL(my_value); static int __init module_a_init(void) { printk(KERN_INFO module_a: init\n); return 0; } static void __exit module_a_exit(void) { printk(KERN_INFO module_a: exit\n); } module_init(module_a_init); module_exit(module_a_exit); MODULE_LICENSE(GPL); MODULE_AUTHOR(Your Name); MODULE_DESCRIPTION(Module that exports symbols); MODULE_VERSION(0.1);// module_b.c - 使用导出符号的模块 #include linux/module.h #include linux/kernel.h #include linux/init.h // 声明外部符号 extern void my_greeting(const char *name); extern int my_value; static int __init module_b_init(void) { printk(KERN_INFO module_b: init\n); // 使用导出的函数 my_greeting(World); // 使用导出的变量 printk(KERN_INFO module_b: my_value %d\n, my_value); return 0; } static void __exit module_b_exit(void) { printk(KERN_INFO module_b: exit\n); } module_init(module_b_init); module_exit(module_b_exit); MODULE_LICENSE(GPL); MODULE_AUTHOR(Your Name); MODULE_DESCRIPTION(Module that uses exported symbols); MODULE_VERSION(0.1);对应的Makefileobj-m module_a.o module_b.o all: make -C /lib/modules/$(shell uname -r)/build M$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M$(PWD) clean内核模块的调试1. 使用printk调试#include linux/kernel.h // 不同级别的日志 printk(KERN_EMERG Emergency message\n); printk(KERN_ALERT Alert message\n); printk(KERN_CRIT Critical message\n); printk(KERN_ERR Error message\n); printk(KERN_WARNING Warning message\n); printk(KERN_NOTICE Notice message\n); printk(KERN_INFO Info message\n); printk(KERN_DEBUG Debug message\n);2. 使用动态调试#include linux/dynamic_debug.h // 动态调试宏 pr_debug(Debug message\n); pr_info(Info message\n); pr_warn(Warning message\n); pr_err(Error message\n);3. 使用kgdb调试# 配置内核支持kgdb make menuconfig # 选择 Kernel hacking - KGDB: kernel debugger # 连接gdb gdb vmlinux (gdb) target remote /dev/ttyS0 (gdb) break myfunction (gdb) continue结论Linux内核的模块化编程是一个功能强大、设计灵活的机制它允许内核功能在运行时动态加载和卸载大大提高了内核的可扩展性和可维护性。通过深入了解Linux内核模块的开发方法、核心机制和最佳实践我们可以更好地开发和调试内核模块扩展内核的功能。在实际应用中我们需要遵循内核模块开发的规范注意模块的加载和卸载顺序正确处理模块的依赖关系避免模块相关的问题。作为系统开发者和内核工程师掌握内核模块化编程的知识是非常重要的它将帮助我们更好地开发和维护内核模块解决模块相关的问题提高系统的可扩展性和可维护性。

相关文章:

Linux内核中的模块化编程详解

Linux内核中的模块化编程详解 引言 模块化编程是Linux内核的一个重要特性,它允许内核功能在运行时动态加载和卸载,提高了内核的灵活性和可扩展性。Linux内核模块可以独立编译和加载,不需要重新编译整个内核,大大简化了内核开发和…...

完整高效解决网易云音乐NCM文件解密难题的实用指南

完整高效解决网易云音乐NCM文件解密难题的实用指南 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式音乐无法在其他设备播放而烦恼吗?ncmdump正是你需要的NCM文件解密利器,这款工…...

3步破解限速难题:Mac版百度网盘极速方案深度解析

3步破解限速难题:Mac版百度网盘极速方案深度解析 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为Mac版百度网盘的龟速下载而苦恼&…...

苦等多年!Compose 终于迎来原生 Media3 播放器

本文首发于公众号“Android技术圈HPro”前两天,Google 正式发布了 Media3 1.10。 对开发者来说最炸的莫不过Compose终于有自己的播放器了! Compose 播放器来了 过去一提 Compose 播放器,很多团队的真实状态其实都差不多。 要么继续用 PlayerV…...

ML307R编译环境搭建:从官方文档到实战避坑指南

1. 为什么需要这份实战指南? 第一次接触ML307R开发板时,我按照官方文档搭建编译环境,结果花了整整两天时间才搞定。官方文档虽然简洁,但很多关键细节都没提到,比如Python版本选择、环境变量配置、依赖库安装等。这些问…...

Amlogic S9xxx Armbian开源项目:让旧电视盒子重获新生的全能解决方案

Amlogic S9xxx Armbian开源项目:让旧电视盒子重获新生的全能解决方案 【免费下载链接】amlogic-s9xxx-armbian Supports running Armbian on Amlogic, Allwinner, and Rockchip devices. Support a311d, s922x, s905x3, s905x2, s912, s905d, s905x, s905w, s905, s…...

键盘鼠标可视化:让你的操作在屏幕上“跳起舞来“的终极指南

键盘鼠标可视化:让你的操作在屏幕上"跳起舞来"的终极指南 【免费下载链接】keyviz Keyviz is a free and open-source tool to visualize your keystrokes ⌨️ and 🖱️ mouse actions in real-time. 项目地址: https://gitcode.com/gh_mir…...

“听劝!”预算1k内吉他别瞎买:雅马哈/布洛克/费森横评,这款单板琴让我惊掉下巴!

准备买第一把吉他了,是不是既兴奋又有点慌?面对琳琅满目的品牌和从几百到几千的价格,心里直打鼓: 太便宜的是不是“烧火棍”?太贵了又怕自己坚持不下去浪费钱。 更怕的是,花了钱买回家,发现声音…...

探索League Akari:基于LCU API的模块化英雄联盟客户端工具集

探索League Akari:基于LCU API的模块化英雄联盟客户端工具集 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League Akari是一个基…...

Arduino实战:如何用旋转编码器控制你的项目(附方向判断代码)

Arduino实战:旋转编码器方向判断与项目集成指南 引言 在创客和电子爱好者的世界里,旋转编码器就像是一个神奇的"旋钮",它能把你的物理转动动作转化为数字信号。想象一下,通过简单的旋转就能精确控制音量大小、菜单选择…...

Figma中文插件:设计师必备的界面汉化神器,让设计效率提升50%

Figma中文插件:设计师必备的界面汉化神器,让设计效率提升50% 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma的英文界面而苦恼吗?FigmaCN…...

终极指南:如何免费升级老旧Mac到最新macOS系统

终极指南:如何免费升级老旧Mac到最新macOS系统 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher是一款革命性的开源工具&a…...

ComfyUI BrushNet终极指南:如何快速实现高质量AI图像修复与扩展

ComfyUI BrushNet终极指南:如何快速实现高质量AI图像修复与扩展 【免费下载链接】ComfyUI-BrushNet ComfyUI BrushNet nodes 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-BrushNet ComfyUI BrushNet 是一款革命性的AI图像修复和扩展插件&#xff0…...

Flowise AI工作流安全通关手册:从零基础入门到攻防专家,全链路守住你的AI核心资产

2026年4月,全球AI圈与网络安全界同步爆发了一场震动行业的大规模攻击事件:黑客利用开源AI工作流编排平台Flowise的CVE-2025-59528满分高危漏洞,对全球公网暴露的上万个AI工作流实例发起无差别攻击。短短一周内,数千个企业与开发者…...

Conan实战指南:从零搭建私有C++依赖仓库

1. 为什么C团队需要私有依赖仓库 在C开发领域,依赖管理一直是个令人头疼的问题。我见过太多团队在项目启动时,把大量时间花在配置第三方库上。有人直接把第三方库源码塞进项目目录,有人要求每个开发者手动安装系统级依赖,还有人写…...

UE5新手必看:新建项目就白屏?三步搞定PostProcessVolume曝光问题

UE5新手避坑指南:三招解决新建项目白屏问题 第一次打开虚幻引擎5(UE5)创建的项目,满心期待看到华丽的默认场景,结果眼前却是一片刺眼的白光——这种"开门黑"体验让不少新手开发者瞬间懵圈。别急着怀疑自己的…...

nRF Connect 介绍和操作入门

nRF Connect 介绍和操作入门 一、nRF Connect 简介 nRF Connect 是由 Nordic Semiconductor 开发的一套强大的低功耗蓝牙(BLE)开发工具集合,主要面向开发者、测试人员以及蓝牙技术爱好者。它分为三个主要版本: 1.1 主要版本版本平…...

有限状态自动机(DFA)在文本处理中的高效应用与实现

1. 有限状态自动机(DFA)到底是什么? 第一次听到"有限状态自动机"这个词时,我也是一头雾水。后来在实际项目中用了几次才发现,它其实就是个"智能开关"——根据不同的输入条件,在预设的几…...

深夜告警炸裂?这份Linux故障排查“作战地图”请收好诺

先唠两句:参数就像餐厅点单 把API想象成一家餐厅的“后厨系统”。 ? 路径参数/dishes/{dish_id} -> 好比你要点“宫保鸡丁”这道具体的菜,它是菜单(资源路径)的一部分。查询参数/dishes?spicytrue&typeSichuan -> 好比…...

RMBG-1.4实战指南:高精度图像抠图开源模型快速上手

RMBG-1.4实战指南:高精度图像抠图开源模型快速上手 1. 为什么你需要RMBG-1.4? 如果你曾经为了抠一张图,在Photoshop里用钢笔工具一点点描边,或者用魔棒工具反复调整容差,那么RMBG-1.4将会彻底改变你的工作方式。 想…...

Intv_AI_MK11人工智能(AI)入门:核心概念图解与首个AI应用创建

Intv_AI_MK11人工智能(AI)入门:核心概念图解与首个AI应用创建 1. 人工智能初体验:从零开始理解AI 想象一下,你正在教一个小朋友认识动物。刚开始,他可能分不清猫和狗的区别,但随着你不断展示图…...

MedGemma-X新手教程:一键搭建AI放射科数字助手

MedGemma-X新手教程:一键搭建AI放射科数字助手 1. 为什么你需要一个能“看懂”X光片的AI助手? 想象一下这个场景:深夜的放射科值班室,你面前堆着几十张待阅的胸片,眼睛已经有些干涩。其中一张片子,右肺中…...

智谱开源视觉模型GLM-4.6V-Flash-WEB效果实测:识别准确,回答智能,小白可上手

智谱开源视觉模型GLM-4.6V-Flash-WEB效果实测:识别准确,回答智能,小白可上手 1. 开箱即用的视觉大模型体验 在AI技术快速发展的今天,一个真正"能用"的视觉大模型远比那些只能在论文里看到的模型更有价值。GLM-4.6V-Fl…...

iOS 26.4越狱深度解析:从技术原理到实战应用的全面指南

iOS 26.4越狱深度解析:从技术原理到实战应用的全面指南 【免费下载链接】Jailbreak iOS 26.4 - 26, 17 - 17.7.5 & iOS 18 - 18.7.3 Jailbreak Tools, Cydia/Sileo/Zebra Tweaks & Jailbreak News Updates || AI Jailbreak Finder 👇 项目地址…...

终极指南:ESLyric-LyricsSource三大逐字歌词格式深度解析与实战部署

终极指南:ESLyric-LyricsSource三大逐字歌词格式深度解析与实战部署 【免费下载链接】ESLyric-LyricsSource Advanced lyrics source for ESLyric in foobar2000 项目地址: https://gitcode.com/gh_mirrors/es/ESLyric-LyricsSource ESLyric-LyricsSource是专…...

卷积神经网络原理详解:使用Phi-3-mini进行交互式学习与代码生成

卷积神经网络原理详解:使用Phi-3-mini进行交互式学习与代码生成 1. 引言:为什么选择CNN作为深度学习入门 卷积神经网络(CNN)是计算机视觉领域的基石技术,从人脸识别到自动驾驶都离不开它。但对于初学者来说&#xff0c…...

网盘下载限速终结者:八大平台一键极速下载的完整解决方案

网盘下载限速终结者:八大平台一键极速下载的完整解决方案 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天…...

Qwen3-0.6B-FP8实战教程:支持中文长上下文的本地化对话微调准备

Qwen3-0.6B-FP8实战教程:支持中文长上下文的本地化对话微调准备 想在自己的电脑上跑一个能聊天的AI,但又担心显卡太差、内存不够?今天给大家介绍一个神器——基于Qwen3-0.6B-FP8模型的本地对话工具。它只有6亿参数,经过FP8量化后…...

百度网盘Mac版SVIP特权完整解锁方案:告别限速困扰

百度网盘Mac版SVIP特权完整解锁方案:告别限速困扰 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘Mac版缓慢的下载速度而烦恼…...

SteamCleaner终极指南:一键释放60GB硬盘空间,让游戏电脑重获新生

SteamCleaner终极指南:一键释放60GB硬盘空间,让游戏电脑重获新生 【免费下载链接】SteamCleaner :us: A PC utility for restoring disk space from various game clients like Origin, Steam, Uplay, Battle.net, GoG and Nexon :us: 项目地址: https…...