首页 > 系统相关 >Linux模块与系统调用

Linux模块与系统调用

时间:2025-01-02 11:29:45浏览次数:6  
标签:调用 module init task exit 模块 Linux printk

模块与系统调用

1. 编写内核模块代码

首先,编写一个简单的“Hello World”内核模块文件 hello_module.c

#include <linux/init.h>     // 用于宏 __init 和 __exit
#include <linux/module.h>   // 用于模块编程基本宏
#include <linux/kernel.h>   // 用于 printk 宏

MODULE_LICENSE("GPL");               // 指定模块许可证
MODULE_AUTHOR("20242826");          // 指定模块作者
MODULE_DESCRIPTION("A simple hello world kernel module"); // 模块描述
MODULE_VERSION("1.0");               // 模块版本

// 初始化函数
static int __init hello_init(void) {
    printk(KERN_INFO "Hello, Kernel!\n"); // 向内核日志打印信息
    return 0;  // 返回0表示成功
}

// 清理函数
static void __exit hello_exit(void) {
    printk(KERN_INFO "Goodbye, Kernel!\n"); // 向内核日志打印信息
}

// 注册初始化和清理函数
module_init(hello_init);
module_exit(hello_exit);

在这个模块中:

  • hello_init 函数在模块加载时运行。
  • hello_exit 函数在模块卸载时运行。
  • printk 是用于内核日志输出的函数,类似于用户空间的 printf

2. 创建Makefile文件

创建一个 Makefile,用来编译内核模块。文件内容如下:

# Makefile
obj-m += hello_module.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

在这个 Makefile 中:

  • obj-m += hello_module.o 指定生成模块的目标文件。
  • make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 命令用当前内核的编译环境编译模块。
  • clean 命令用于清理编译生成的文件。

3. 编译内核模块

在包含 hello_module.cMakefile 的目录中,运行以下命令来编译模块:

make

编译成功后,将生成 hello_module.ko 文件,这就是编译完成的内核模块文件。

01

4. 加载和卸载内核模块

加载模块

要加载模块,可以使用 insmod 命令:

sudo insmod hello_module.ko

成功加载模块后,内核日志中会出现 Hello, Kernel! 的信息。可以通过以下命令查看内核日志:

sudo dmesg | tail

02

卸载模块

要卸载模块,可以使用 rmmod 命令:

sudo rmmod hello_module

卸载模块后,内核日志中会显示 Goodbye, Kernel! 信息。
03

5.编译模块实现输出当前进程信息的功能

#include <linux/init.h>      // 用于宏 __init 和 __exit
#include <linux/module.h>    // 用于模块编程基本宏
#include <linux/kernel.h>    // 用于 printk 宏
#include <linux/sched.h>     // 用于获取当前进程信息
#include <linux/sched/signal.h>

MODULE_LICENSE("GPL");               // 模块许可证
MODULE_AUTHOR("20242826");          // 模块作者
MODULE_DESCRIPTION("A module to print current process info"); // 模块描述
MODULE_VERSION("1.0");               // 模块版本

// 初始化函数
static int __init module2_init(void) {
    printk(KERN_INFO "Module2 loaded\n");
    printk(KERN_INFO "Current Process Info:\n");
    printk(KERN_INFO "Process ID: %d\n", current->pid);
    printk(KERN_INFO "Process Name: %s\n", current->comm);
    return 0;  // 返回0表示成功
}

// 清理函数
static void __exit module2_exit(void) {
    printk(KERN_INFO "Module2 unloaded\n");
}

// 注册初始化和清理函数
module_init(module2_init);
module_exit(module2_exit);

代码说明

  • current 是一个指向当前执行进程的 task_struct 指针,task_struct 是包含进程信息的内核结构体。
  • current->pid 表示当前进程的ID。
  • current->comm 表示当前进程的名称。
# Makefile
obj-m += module2.o   # 指定编译生成的目标对象

all:
	# 使用 Tab 键缩进
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	# 使用 Tab 键缩进
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

make
sudo insmod module2.ko
sudo dmesg | tail
# 卸载模块
sudo rmmod module2

04

6.编译模块实现读取进程链表的功能

#include <linux/init.h>        // 用于宏 __init 和 __exit
#include <linux/module.h>      // 用于模块编程基本宏
#include <linux/kernel.h>      // 用于 printk 宏
#include <linux/sched.h>       // 用于 task_struct 结构体
#include <linux/sched/signal.h> // 用于 next_task 宏

MODULE_LICENSE("GPL");
MODULE_AUTHOR("20242826");
MODULE_DESCRIPTION("A module to list all processes in the process list");
MODULE_VERSION("1.0");

static int __init module3_init(void) {
    struct task_struct *task;

    printk(KERN_INFO "Module3 loaded: Listing all processes\n");

    // 遍历进程链表
    for_each_process(task) {
        printk(KERN_INFO "Process: %s [PID: %d]\n", task->comm, task->pid);
    }

    return 0;
}

static void __exit module3_exit(void) {
    printk(KERN_INFO "Module3 unloaded\n");
}

module_init(module3_init);
module_exit(module3_exit);

代码说明

  • for_each_process(task) 是 Linux 内核提供的一个宏,用于遍历所有进程。它会依次遍历所有 task_struct 结构体,将每个进程的指针赋值给 task 变量。
  • task->comm 存储进程名称,task->pid 存储进程 ID。
    该模块在加载时输出所有进程的名称和进程ID。
# Makefile
obj-m += module3.o   # 指定编译生成的目标对象

all:
	# 使用 Tab 键缩进
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	# 使用 Tab 键缩进
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

make
sudo insmod module3.ko
sudo dmesg | tail -n 50
# 卸载模块
sudo rmmod module3

05

7. 清理编译生成的文件

执行以下命令清理生成的文件:

make clean

总结

以上步骤完成了Linux内核模块编写、编译、加载和卸载的流程。

标签:调用,module,init,task,exit,模块,Linux,printk
From: https://www.cnblogs.com/Arisf/p/18647281

相关文章

  • linux安装php运行环境
    https://github.com/wintercoder/datamaker开源的mysql做假数据项目 一、linux下安装php集成环境sudoapt-getinstallhttpdservicehttpdstart主配置目录:/etc/httpd/conf/主配置文件:/etc/httpd/conf/httpd.conf/子配置目录:/etc/httpd/conf.d/子配置文件:/etc/http......
  • Dify 框架连接 PGSQL 数据库与 Sandbox 环境下的 Linux 系统调用权限问题
    Dify框架连接PGSQL数据库与Sandbox环境下的Linux系统调用权限问题背景在使用Dify框架进行开发时,遇到了两个主要的技术挑战:代码节点连接到PGSQL(PostgreSQL)数据库。解决沙盒环境中由于系统调用限制导致的“operationnotpermitted”错误。本文档将详细描述如何解......
  • linux ubuntu更改软件源
    更换步骤sudocp/etc/apt/sources.list /etc/apt/sources.list.backsudovim/etc/apt/sources.list替换为下面内容debhttps://mirrors.ustc.edu.cn/ubuntu/bionicmainrestricteduniversemultiversedeb-srchttps://mirrors.ustc.edu.cn/ubuntu/bionicmainrestric......
  • linux mint安装hadoop
    一、安装安装sshopenssh-server 配置jdk环境变量~/.bashrc参考exportJAVA_HOME=/opt/jdk1.7.0_55/exportJRE_HOME=${JAVA_HOME}/jreexportCLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/libexportPATH=${JAVA_HOME}/bin:$PATH exportHADOOP_HOME=/opt/Servers/hadoo......
  • Linux安装nodejs npm
    1、检查whereisnodejswhereisnpm2、下载wget-chttps://npm.taobao.org/mirrors/node/v12.12.0/node-v12.12.0-linux-x64.tar.xztar-xvfnode-v12.12.0-linux-x64.tar.xzmvnode-v12.12.0-linux-x64nodejsmv/root/nodejs//usr/sbin/3、配置软连接ln-s/usr/sbin/......
  • 一文读懂 Linux top 命令
    一文读懂Linuxtop命令在Linux系统管理与性能调优的“武器库”中,top命令无疑是一把极为锋利的“利刃”。它能够实时动态地展示系统关键运行指标,犹如系统运行状态的“监控大屏”,为管理员和开发者快速洞察系统健康程度、资源分配状况提供关键信息。下面,就来详细拆解这个......
  • 深入理解 Linux 中的“rm -rf”:威力与风险并存
    深入理解Linux中的“rm-rf”:威力与风险并存在Linux系统的命令行世界里,“rm-rf”可谓是声名远扬,它是一条用于删除文件与目录的强力指令。对于经验丰富的系统管理员和开发者而言,它是高效清理磁盘空间、整理文件系统的得力助手;然而,倘若使用不当,也极有可能酿成数据丢失......
  • 在NodeJS中内置的fs模块有哪几部分组成?
    在Node.js中,内置的fs模块(文件系统模块)主要由以下几部分组成:文件读取:fs.readFile(file[,options],callback):异步读取文件内容。fs.readFileSync(file[,options]):同步读取文件内容,返回文件数据。文件写入:fs.writeFile(file,data[,options],callback):异步写......
  • Linux云服务器修改远程SSH端口后无法连接怎么办?
    当您在Linux云服务器上修改了SSH服务的默认端口(通常是22)之后,发现无法从外部网络连接到该服务器时,可能是由于以下几个原因造成的。以下是详细的排查步骤及解决方案:确认防火墙设置:首先需要检查服务器上的防火墙规则是否允许新的SSH端口通过。对于CentOS/RHEL系统,可以使用firewall......
  • NodeJS的模块分为哪几类?
    Node.js的模块主要分为以下三类:内置模块:这些是由Node.js官方提供的模块,内置于Node.js运行环境中。它们提供了许多基本功能,如文件系统操作(fs)、路径处理(path)、HTTP服务器创建(http)等。内置模块无需额外安装,可以直接通过require()函数引入使用。自定义模块:自定义模块是用户根据......