内核模块是Linux内核向外部提供的一个接口,其全称是
动态可加载内核模块(Loadabkle Kernel Module,LKM)。
Linux
内核之所以提供模块机制,是因为它本身是一个单内核(
monolithic
kernel
)。单内核的最大优点是效率高,因为所有的内
容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。
一、什么是模块
模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或内核中其他上层功能。
二、
编写一个简单的模块
模块和内核都在内核空间运行,
模块编程在一定意义上说就是内核编程。因为内核版本的每次变化,其中的某些函数名也会相应地发生变化,因此模块编程与内核版本密切相关。
第一个内核模块:
内核版本:2.6.31-4
在RedFlag 6.0测试通过
/*
* hellomod.c
* 第一个内核模块
* author:cm
* date:2010-3-28
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
static int __init lkp_init(void)
{
printk("<1>Hello,Kernel! from the kernel space...\n");
return 0;
}
static void __exit lkp_cleanup(void)
{
printk("<1>Goodbye,Kernel! leaving the space...\n");
}
module_init(lkp_init);
module_exit(lkp_cleanup);
MODULE_LICENSE("GPL");
说明:
8~10行 一些必要的头文件
所有模块都要使用头文件module.h,此文件必须包含进来。
头文件kernel.h包含了常用的内核函数。
头文件init.h包含了宏_init和_exit,它们允许释放内核占用的内存。
12~16行
这是模块的初始化函数,它必需包含诸如要编译的代码、初始化数据结构等内容
printk()函数 该函数是由内核定义的,功能与C库中的printf()类似,它把要打印的信息输出到终端或系统日志。字符串中的<1>是输出的级别,表示立即在终端输出。
18~21行
这是模块的退出和清理函数。此处可以做所有终止该驱动程序时相关的清理工作。
23~24行
函数module_init()和module_exit()是模块编程中最基本也是必须的两个函数。module_init()向内核注册模块所提供的新功能,而module_exit()注销由模块提供的功能。
module_init() 是驱动程序初始化的入口点。对于内置模块,内核在引导时调用该入口点;对于可加载模块则在该模块插入内核时才调用,在卸载模块时调用module_exit()函数。
25行
GNU公共许可证 (必须)
编译
编译工具:gcc make
Makefile文件:
#Makefile2.6
obj-m += hellomod.o #产生hellomod模块的目标文件
CURRENT_PATH := $(shell pwd) #模块所在的当前路径
LINUX_KERNEL := $(shell uname -r) #内核版本
#内核源码的绝对路径 (RedFlag 6.0)
LINUX_KERNEL_PATH := /usr/src/kernels/2.6.31-4-i686
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #编译模块
clean:
rm -rf *.mod.c *.o *.ko *.markers *.symvers *.order #清理
执行make命令,会自动生成模块相关文件(如 .o .ko文件)
插入模块到内核
[root@localhost module]# insmod hellomod.ko
成功插入后,可以通过dmesg命令查看这个模块所执行的显示内容
[root@localhost module]# dmesg
...
Hello,Kernel! from the kernel space...
卸载模块
[root@localhost module]# rmmod hellomod
再次执行dmesg 显示
Hello,Kernel! from the kernel space...
Goodbye,Kernel! leaving the space...
注:查看(dmesg)其实是看日志,只要是看日志的方法应该都是可以的比如:tail /var/log/messages
分享到:
相关推荐
Linux驱动开发之编写第一个内核模块--Hello World源码, 亲测OK,对应文章链接: https://dingdong.blog.csdn.net/article/details/106329048
最后第4章是驱动设计指导规范, 它是一个提纲性质的, 提醒我们在编写内核模块时的主要注意事项. 我们在做具体项目的时候, 可以查询此章节获得一个快速指引, 如果你对快速指引的细节遗忘了, 则需要重新理解第3章的内容...
**2.1 HelloWorld(第1部分):创建基本的内核模块** 在这个阶段,我们的目标是创建一个最基本的内核模块,它能够在加载时打印一条消息。我们将使用`printk()`函数来输出这条信息。 ```c #include #include ...
6. **实验实践**:通过编写一个简单的内核模块,如显示进程控制块(PCB)信息,可以加深对内核模块工作原理的理解。这通常涉及使用内核API来访问和处理内核数据结构,例如,使用`current`宏获取当前进程的PCB,然后...
### Ubuntu下内核编程之第一个模块 #### 一、引言 在Linux系统中,内核模块是一种重要的软件组件,它允许用户动态地添加或移除功能而不必重启整个系统。这种灵活性对于系统管理和应用程序开发都非常有用。本文将...
这是每个编程学习者接触的第一个程序,但在内核模块中,它的作用是展示如何与内核交互。Exhello.c中通常会包含以下关键部分: 1. `#include <linux/init.h>` 和 `#include <linux/module.h>`:这两个头文件包含了...
在这个主题中,我们将深入探讨如何编写属于你的第一个模块,特别是在Linux内核环境中。 首先,我们需要了解模块在Linux内核中的作用。Linux内核模块是一种可加载的代码片段,它们可以在运行时插入到内核中,增加新...
这通常是初学者入门内核编程的第一个练习,因为它涉及到基本的模块入口和出口函数。模块入口函数是`init_module()`,它在模块被加载到内核时执行;退出函数是`cleanup_module()`,在模块被卸载时调用。这两个函数是...
这意味着操作系统内核和第三方内核模块都运行在同一特权级下,共享同一个虚拟地址空间。因此,第三方内核模块可以完全访问系统空间内的内存,从而构成极大的安全隐患。 尽管Windows系统提供了一些机制(如驱动签名...
Linux内核模块编程入门可以分为几个步骤:首先,需要编写模块的源代码,包括头文件、Makefile文件和模块的实现代码。其次,需要使用gcc编译器和ld链接器编译和链接模块。最后,需要使用insmod命令加载模块到内核中...
1. **初始化函数**:这是模块加载时调用的第一个函数,通常用于注册设备或执行其他初始化操作。 2. **退出函数**:当模块被卸载时,此函数会被调用,用于清理模块创建的所有资源。 ### 内核模块证书和文档说明 ...
本实验手册的第12部分主要聚焦于Linux内核模块参数的使用和管理,通过实践操作帮助学生深入理解如何在Linux环境下编写、编译、加载以及调试内核模块,并特别关注了内核模块参数的配置方法。这对于学习Linux内核编程...
本篇文章将深入探讨如何在Ubuntu环境下编写你的第一个内核模块——一个简单的“Hello, World!”模块。 首先,我们要了解什么是内核模块。内核模块是可加载到运行中的Linux内核中的代码片段,它们允许我们向内核添加...
第二部分:编写一个自己的内核模块 2.1 实验内容与预备知识 内核模块是Linux内核的一部分,可以在需要时动态加载和卸载。预备知识包括Linux内核编程接口,如sysfs、procfs,以及如何使用module_init和module_exit宏...
描述中提到了实验基于"Operating System Concepts"教材的第四章和第六章,这通常涉及操作系统的基本概念和进程管理,同时参考了"边干边学Linux内核指导2.2",这部分可能涉及了内核模块的编写和Linux内核的输入输出...
这一节介绍了编写第一个内核模块的基本步骤,包括必要的头文件、函数声明和模块初始化。 #### 2.1.1 介绍printk() `printk()`是内核模块中常用的调试函数,用于向系统日志输出信息。它类似于标准C库中的`printf()`...
- **背景**: 在学习编程时,“Hello, World”程序通常作为入门的第一个程序。对于Linux内核编程而言,也是如此。 - **基本结构**: 一个典型的内核模块至少包含两个函数: - `init_module()`: 当模块被加载到内核时...