本文主要是介绍Linux 使用C语言来加载和卸载内核模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 一、insmod/rmmod
- 1.1 insmod
- 1.2 rmmod
- 二、C语言示例
- 2.1 syscall
- 2.2 dmeo
一、insmod/rmmod
1.1 insmod
Linux 使用insmod来加载内核模块:
NAMEinsmod - Simple program to insert a module into the Linux Kernel
使用strace来追踪其过程:
[root@localhost helloworld]# strace insmod helloworld.ko
execve("/usr/sbin/insmod", ["insmod", "helloworld.ko"], 0x7fffff3cc6e8 /* 27 vars */) = 0
......
open("/root/module/helloworld/helloworld.ko", O_RDONLY|O_CLOEXEC) = 3
.....
finit_module(3, "", 0) = 0
......
close(3) = 0
[root@localhost helloworld]#
可以看到使用finit_module系统调用来加载内核模块:
// linux-5.15/kernel/module.cSYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
{......return load_module(&info, uargs, flags);
}
1.2 rmmod
Linux 使用shell命令rmmod来卸载内核模块:
NAMErmmod - Simple program to remove a module from the Linux Kernel
使用strace来追踪其过程:
[root@localhost helloworld]# strace rmmod helloworld
execve("/usr/sbin/rmmod", ["rmmod", "helloworld"], 0x7ffdc01ddef8 /* 27 vars */) = 0
......
delete_module("helloworld", O_NONBLOCK) = 0
// linux-5.15/kernel/module.cSYSCALL_DEFINE2(delete_module, const char __user *, name_user,unsigned int, flags)
{......
}
二、C语言示例
2.1 syscall
NAMEsyscall - indirect system callSYNOPSIS#define _GNU_SOURCE /* See feature_test_macros(7) */#include <unistd.h>#include <sys/syscall.h> /* For SYS_xxx definitions */int syscall(int number, ...);DESCRIPTIONsyscall() is a small library function that invokes the system call whose assembly language interface has the specified number with the specified arguments. Employ‐ing syscall() is useful, for example, when invoking a system call that has no wrapper function in the C library.syscall() saves CPU registers before making the system call, restores the registers upon return from the system call, and stores any error code returned by the sys‐tem call in errno(3) if an error occurs.Symbolic constants for system call numbers can be found in the header file <sys/syscall.h>.
syscall()是一个小型的库函数,用于调用具有指定编号和指定参数的汇编语言接口的系统调用。使用syscall()函数非常有用,特别是在调用在C库中没有封装函数的系统调用时。
2.2 dmeo
(1)C语言示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <fcntl.h>int load_module(const char *modulePath) {int fd = open(modulePath, O_RDONLY);if (fd < 0) {perror("Failed to open module");return 1;}int result = syscall(__NR_finit_module, fd, "", 0);if (result < 0) {perror("Failed to load module");close(fd);return 1;}printf("Module loaded successfully\n");close(fd);return 0;
}int unload_module(const char *moduleName) {int result = syscall(__NR_delete_module, moduleName, O_NONBLOCK);if (result < 0) {perror("Failed to unload module");return 1;}printf("Module unloaded successfully\n");return 0;
}int main() {const char *modulePath = "./helloworld.ko";const char *moduleName = "helloworld";int loadResult = load_module(modulePath);if (loadResult != 0) {printf("Failed to load module\n");return 1;}int unloadResult = unload_module(moduleName);if (unloadResult != 0) {printf("Failed to unload module\n");return 1;}return 0;
}
(2)内核模块示例:
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>//内核模块初始化函数
static int __init lkm_init(void)
{printk("Hello World\n");return 0;
}//内核模块退出函数
static void __exit lkm_exit(void)
{printk("Goodbye\n");
}module_init(lkm_init);
module_exit(lkm_exit);MODULE_LICENSE("GPL");
结果:
[root@localhost helloworld]# ./a.out
Module loaded successfully
Module unloaded successfully[root@localhost helloworld]# dmesg -c
[368000.085692] Hello World
[368000.086536] Goodbye
这篇关于Linux 使用C语言来加载和卸载内核模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!