You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建内核模块时遇“vmlinux不可用”错误的解决问询

问题分析与解决思路

编译时BTF提示的含义

Skipping BTF generation for /home/dpb/Documents/CSE_420/p4/try2/mymodule2.ko due to unavailability of vmlinux 提示的核心含义是:
内核模块编译时会尝试生成**BTF(BPF类型格式)**信息——这是内核用于BPF调试、类型校验的标准格式,但系统中找不到带完整调试符号的内核镜像文件vmlinux,因此跳过BTF生成步骤。

这个提示本身不会直接导致模块无法加载,但你的同学未遇到该问题,是因为他们的系统安装了对应内核版本的调试包,或者内核编译时自带了vmlinux文件。

解决BTF提示的两种方法

  • 安装内核调试包:
    • Ubuntu/Debian系:执行 sudo apt install linux-image-$(uname -r)-dbg
    • RHEL/CentOS系:执行 sudo dnf install kernel-debuginfo-$(uname -r)
  • 编译时禁用BTF生成:修改Makefile的all目标,添加BTF=0参数:
    KERNEL_SOURCE := /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)
    obj-m += mymodule2.o
    
    all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) BTF=0 modules
    
    clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
    

模块加载失败的核心问题

使用insmod加载时卡住,是因为代码存在空指针访问的致命错误:

  1. 全局变量p_id未初始化,也没有提供外部传入参数的方式,加载时它的值是随机垃圾值,调用find_get_pid(p_id)几乎必然返回NULL
  2. 直接对NULL指针调用pid_task,会触发内核空指针异常,导致系统卡住甚至崩溃

代码修正方案

以下是修复后的完整代码(包含参数传入、空指针检查、资源释放、拼写修正):

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pid_namespace.h>

int p_id;
struct pid *pid_struct;
struct task_struct *task;

/* Meta Information */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Devin 4 GNU/Linux");
MODULE_DESCRIPTION("A module to access task_struct via PID");
// 允许加载模块时传入目标PID
module_param(p_id, int, 0644);
MODULE_PARM_DESC(p_id, "The PID of the process to inspect");

/* This function is called when the module is loaded into the kernel */
static int __init ModuleInit(void) {
    // 检查传入的PID合法性
    if (p_id <= 0) {
        printk(KERN_ERR "Invalid PID: %d, must be positive\n", p_id);
        return -EINVAL;
    }

    pid_struct = find_get_pid(p_id);
    if (!pid_struct) {
        printk(KERN_ERR "Process with PID %d not found\n", p_id);
        return -ESRCH;
    }

    task = pid_task(pid_struct, PIDTYPE_PID);
    if (!task) {
        printk(KERN_ERR "Failed to get task_struct for PID %d\n", p_id);
        put_pid(pid_struct); // 释放pid结构体,避免内存泄漏
        return -EINVAL;
    }

    // 输出进程信息
    printk(KERN_INFO "PID: %d\n", p_id);
    printk(KERN_INFO "Name: %s\n", task->comm);
    // 如需获取内存页信息,需先检查task->mm是否非空(内核线程无mm结构体)
    // if (task->mm) printk(KERN_INFO "Total Pages in KB: %lu\n", task->mm->total_vm * PAGE_SIZE / 1024);

    put_pid(pid_struct); // 释放pid结构体资源
    return 0;
}

/* This function is called when the module is removed from the kernel */
static void __exit ModuleExit(void) {
    printk(KERN_INFO "Bye!\n");
}

module_init(ModuleInit);
module_exit(ModuleExit);

正确加载模块的方式

编译完成后,传入目标进程的PID(例如1234)加载模块:

sudo insmod mymodule2.ko p_id=1234

通过内核日志查看输出:

dmesg | tail -20

内容的提问来源于stack exchange,提问作者Devin Bowen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 07:50:17