linux内核添加c代码,如何从C代码加载Linux内核模块?
Ciro Santill..
19
最小的可運行示例
使用這個簡單的參數打印機模塊在QEMU + Buildroot VM和Ubuntu 16.04主機上進行了測試.
我們使用init_module/ finit_module和remove_module Linux系統調用.
Linux內核為模塊插入提供了兩個系統調用:
init_module
finit_module
和:
man init_module
文件:
finit_module()系統調用類似于init_module(),但是從文件描述符fd讀取要加載的模塊.當內核模塊的真實性可以從它在文件系統中的位置確定時,它是有用的; 在可能的情況下,可以避免使用加密簽名的模塊來確定模塊的真實性的開銷.param_values參數與init_module()相同.
glibc似乎沒有為它們提供C包裝器,所以我們只創建自己的包裝器syscall.
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#define init_module(module_image, len, param_values) syscall(__NR_init_module, module_image, len, param_values)
#define finit_module(fd, param_values, flags) syscall(__NR_finit_module, fd, param_values, flags)
int main(int argc, char **argv) {
const char *params;
int fd, use_finit;
size_t image_size;
struct stat st;
void *image;
/* CLI handling. */
if (argc < 2) {
puts("Usage ./prog mymodule.ko [args="" [use_finit=0]");
return EXIT_FAILURE;
}
if (argc < 3) {
params = "";
} else {
params = argv[2];
}
if (argc < 4) {
use_finit = 0;
} else {
use_finit = (argv[3][0] != '0');
}
/* Action. */
fd = open(argv[1], O_RDONLY);
if (use_finit) {
puts("finit");
if (finit_module(fd, params, 0) != 0) {
perror("finit_module");
return EXIT_FAILURE;
}
close(fd);
} else {
puts("init");
fstat(fd, &st);
image_size = st.st_size;
image = malloc(image_size);
read(fd, image, image_size);
close(fd);
if (init_module(image, image_size, params) != 0) {
perror("init_module");
return EXIT_FAILURE;
}
free(image);
}
return EXIT_SUCCESS;
}
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#define delete_module(name, flags) syscall(__NR_delete_module, name, flags)
int main(int argc, char **argv) {
if (argc != 2) {
puts("Usage ./prog mymodule");
return EXIT_FAILURE;
}
if (delete_module(argv[1], O_NONBLOCK) != 0) {
perror("delete_module");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Busybox源解釋
Busybox提供insmod_main,因為它是為極簡主義而設計的,我們可以嘗試從那里推斷它是如何完成的.
在版本1.24.2上,入口點是IF_FEATURE_2_4_MODULES功能modutils.c.
它bb_init_module是對較舊的Linux內核2.4模塊的可選支持,因此我們暫時可以忽略它.
那只是轉發bb_init_module功能mmap.
try_to_mmap_module 嘗試兩件事:
image_size文件到內存通過.ko.
這總是設置malloc為xmalloc_open_zipped_read_close文件的大小作為副作用.
如果失敗,try_to_mmap_module 將文件存入內存image.
如果文件是zip文件,則此函數可選擇首先解壓縮文件,否則只對其進行malloc.
我不明白為什么這個拉鏈業務已經完成,因為我們甚至不能依賴它,因為""它似乎并沒有解壓縮.
終于來了電話:
init_module(image, image_size, options);
insmod file.elf放在內存中的可執行文件在哪里,init_module如果我們調用ulibc沒有進一步的參數,則選項就是這樣.
init_module 以上提供:
#ifdef __UCLIBC__
extern int init_module(void *module, unsigned long len, const char *options);
extern int delete_module(const char *module, unsigned int flags);
#else
# include
# define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
#endif
man init_module是一個嵌入式libc實現,它似乎提供syscall.
如果它不存在,我認為glibc是假定的,但正如init_module所說:
glibc不支持init_module()系統調用.glibc頭文件中沒有提供聲明,但是,通過歷史的怪癖,glibc會為此系統調用導出ABI.因此,為了使用這個系統調用,在代碼中手動聲明接口就足夠了; 或者,您可以使用syscall(2)調用系統調用.
BusyBox明智地遵循finit_moduleglibc提供的建議和用法,并提供用于系統調用的C API.
總結
以上是生活随笔為你收集整理的linux内核添加c代码,如何从C代码加载Linux内核模块?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uefi 嵌入式Linux,面向嵌入式平
- 下一篇: linux at shell,shell