内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。模块具有以下特点:
1 模块本身不被编译入内核映像,从而控制了内核的大小
2 模块一旦被加载,它就和内核中的其他部分一样
一、 什么是模块
模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。
首先编写hello.c文件
#include<linux/init.h>
#include<linux/module.h>
//模块许可证声明
MODULE_LICENSE("Dual BSD/GPL");
//模块加载函数
static int hello_init(void)
{
printk("Imagination is more important than knowledge !\n");
return 0;
}
//模块卸载函数
static void hello_exit(void)
{
printk("hello world exit ! Congratulations!\n");
}
//这是驱动程序初始化的入口点。对于内置模块,内核在引导时调用该入口 //点;
对于可加载模块则在该模块插入内核时才调用。
module_init(hello_init);
//对于可加载模块,内核在此处调用module_cleanup()函数,而对于内置 //的模块,
它什么都不做。
module_exit(hello_exit);
//可选
MODULE_AUTHOR("IMAGINECUP");
MODULE_DESCRIPTION("A simple Hello World Module");
MODULE_ALIAS("A simplest module");
编写Makefile文件
obj-m +=hello.o #产生hello模块的目标文件
CURRENT_PATH :=$(shell pwd) #模块所在的当前路径
LINUX_KERNEL :=$(shell uname -r) #Linux内核源代码的当前版本
LINUX_KERNEL_PATH :=/usr/src/linux-headers-$(LINUX_KERNEL) #Linux 内核源代码的绝对路径
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #编译模 块
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean #清理
完成上述两个步骤,然后再模块所在路径运行make命令,即生成模块目标文件(hello.ko)
然后你可以运行insmod命令来加载模块,当模块加载后你可以通过lsmod查看模块是否被加载进去。rmmod命令用来卸载模块,dmesg命令可以查看模块执行的结果.
知识点:
内核符号表:
内存地址 符号名 [所属模块]
在模块编程中,可以根据符号名从这个文件中检索出其对应的地址,然后直接访问该地址从而获得内核数据。第三列“所属模块”指符号所在的模块名,对于从内核这一母模块移出的符号,这一列为空。
可通过/proc/kallsyms查看模块输出的内核符号
模块依赖
如前所述,内核符号表记录了所有模块可以访问的符号及相应的地址。当一个新的模块被装入内核后,它所申明的某些符号就会被登记到这个表中,而这些符号可能被其他模块所引用,这就引出了模块依赖这个问题。
一个模块A引用另一个模块B所移出的符号,我们就说模块B被模块A引用,或者说模块A依赖模块B。如果要链接模块A,必须先链接模块B。这种模块间相互依赖的关系就叫模块依赖。
模块引用计数器
为 了确保模块安全地卸载,每个模块都有一个引用计数器。当执行模块所涉及的操作时就递增计数器,在操作结束时就递减这个计数器;另外,当模块B被模块A引用 时,模块B的引用计数就递增,引用结束,计数器递减。什么时候可以卸载这个模块?当然只有这个计数器值为0的时候,例如,当一个文件系统还被安装在系统上 时就不能将其卸载,当这个文件系统不再被使用时,引用计数器就为0,于是可以卸载。
分享到:
相关推荐
Linux内核模块编译通常涉及以下步骤: 1. 获取源码:如果你想要添加的功能或驱动不在预设核心中,你需要从硬件厂商或开源社区获取相应的源码。比如,Intel网络卡的新驱动可以从其官方网站下载。 2. 解压缩源码:将...
在Android开发中,单个模块编译是一种常见的实践,它允许开发者独立地构建和测试应用程序或库的一个特定部分,而不必整个项目一起编译。这对于大型项目尤其有用,因为这样可以提高开发效率并减小程序构建时间。下面...
### Linux内核模块编译方法 #### 概述 在Linux操作系统中,内核作为操作系统的核心部分,负责管理和调度硬件资源、提供系统调用接口等关键功能。为了满足不同的应用场景需求,用户通常需要对内核进行扩展或定制,...
以上就是基于Fedora 9的Linux驱动程序模块编译的基本步骤和注意事项,对于初学者来说,这是一个很好的起点,可以理解内核模块的构建流程和生命周期。随着对内核编程的深入,可以尝试更复杂的驱动程序开发,进一步...
总结来说,基于Mini2440的Linux驱动程序模块编译测试是一个涉及硬件理解、内核编程、构建工具使用等多个环节的过程。通过实践,不仅可以提升对Linux内核机制的理解,还能掌握驱动开发的基本技能,为后续的嵌入式开发...
Linux内核配置模块编译安装指南 Linux内核结构非常庞大,包含的组件也非常多,想要把我们需要的部分添加到内核中,有两个方法:直接编译进内核和模块机制。直接编译进内核有两个缺点,一是生成的内核过大,二是每次...
安信可科技ESP8266模块编译平台是一个为ESP8266模块设计的集成开发环境(IDE),它集成了ESP8266的开发工具链、编译器和相关软件。ESP8266模块是一款流行的低成本Wi-Fi模块,具有完整的TCP/IP协议栈和微型控制器功能...
Linux 内核模块的编译详解 Linux 内核模块的编译是 Linux 内核开发中的一个重要步骤。编译 Linux 内核模块需要准备好内核模块源码、编写 Makefile 文件、编译模块、加载/卸载模块等步骤。 1. 准备内核模块源码 在...
Linux内核模块编译Makefile详解 在Linux内核模块编译中,Makefile扮演着非常重要的角色。Makefile是用于编译Linux内核模块的配置文件,它定义了编译模块所需的各种规则和依赖关系。在本文中,我们将详细解释Linux ...
这个“opencv3.4+contrib模块编译好的安装包”提供了预编译的OpenCV 3.4版本,特别是包含了 contrib 模块,这个模块包含了额外的、非官方的、可能还在开发中的功能,对于研究者和开发者来说非常有价值。 1. **...
### Perl 下 Pdk 模块编译 Perl 程序的方法 #### 一、概述 在 Perl 开发中,为了方便部署与分发程序,有时我们需要将 Perl 脚本编译成可执行文件(如 EXE 文件),而不是简单的文本格式源代码文件。Pdk 模块就是...
这个名为“易语言远控完美框架无模块编译可用”的资源,显然是一款利用易语言开发的远程控制软件框架。远程控制软件允许用户在不同设备之间进行交互,例如远程桌面操作、文件传输等,广泛应用于技术支持、系统管理等...
本文档主要介绍了如何在Linux Ubuntu 10.04 64bit环境下编译MTK包,包括模块编译的过程。以下是详细步骤: 首先,你需要确保拥有一个合适的开发环境,即Linux Ubuntu 10.04 64位操作系统。在这个环境中,你需要处理...
在深入理解Hadoop模块编译和日志调试的过程中,我们需要关注几个关键点,包括源码编译、模块替换、日志级别的控制以及日志调试的方法。以下是对这些内容的详细阐述: 1. **源码编译与模块替换** - **源码编译**:...
标题中的“易语言模块编译”指的是使用易语言这一编程工具进行模块的编译过程。易语言是一种以中文为编程语法的编程环境,旨在降低编程的门槛,让不懂英文的人也能进行程序开发。模块编译是将易语言的源代码模块转化...
linux—unix课件\第九讲-2 内核模块编译.ppt
自己写的一个编译用于linux2.6.x驱动模块编译和管理的makefile脚本。
《易语言模块守护反编译工具V5.93版》是一款专为易语言开发者设计的安全检测工具,其主要功能是帮助用户检测模块的安全性,防止潜在的后门和病毒侵入。作为一款软件/插件,它的重要性在于能够保护程序员的劳动成果,...
通过本实验,使学生掌握在Linux系统内核中单独编译、加载和卸载所需的模块的一般方法和过程。
以下是一些优化Maven多模块项目编译速度的策略: 1. **利用多核CPU并行编译**: Maven的 `-T` 参数可以用来指定并发编译的线程数。例如,`-T 4C` 表示使用4个CPU核心进行并行编译,这样能充分利用硬件资源,加快...