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

Linux内核模块新手求助:获取init_task信息时出现段错误

问题排查与解决方案

核心问题原因

  • find_vpid() 和 find_task_by_vpid() 仅用于查找用户空间可见的进程PID,而PID为0的init_task(idle进程)是内核专属进程,并不存在于用户空间PID命名空间中,因此这两个函数会返回NULL。直接访问NULL指针的state成员必然触发段错误。
  • 代码中用%s打印task->state属于格式错误:task->state是整数类型的进程状态位,并非字符串,直接打印会导致内存访问异常或输出乱码。

正确实现方式

方法1:直接引用init_task

init_task是内核导出的全局变量,可直接访问:

#include <linux/sched.h>
#include <linux/init.h>
#include <linux/module.h>

static void init_task_info(void) {
    struct task_struct *task = &init_task;
    const char *state_str;

    // 将进程状态值转换为可读字符串
    switch (task->state) {
        case TASK_RUNNING:          state_str = "TASK_RUNNING"; break;
        case TASK_INTERRUPTIBLE:    state_str = "TASK_INTERRUPTIBLE"; break;
        case TASK_UNINTERRUPTIBLE:  state_str = "TASK_UNINTERRUPTIBLE"; break;
        case __TASK_STOPPED:        state_str = "__TASK_STOPPED"; break;
        case __TASK_TRACED:         state_str = "__TASK_TRACED"; break;
        default:                    state_str = "UNKNOWN"; break;
    }

    printk(KERN_INFO "init_task PID: %d, state: %s\n", task->pid, state_str);
}

static int __init mymodule_init(void) {
    init_task_info();
    return 0;
}

static void __exit mymodule_exit(void) {
    printk(KERN_INFO "Module exited\n");
}

module_init(mymodule_init);
module_exit(mymodule_exit);
MODULE_LICENSE("GPL");

方法2:遍历进程列表查找PID0

如果需要通过PID匹配的方式查找,可使用for_each_process宏遍历所有内核进程:

#include <linux/sched.h>
#include <linux/init.h>
#include <linux/module.h>

static void init_task_info(void) {
    struct task_struct *task;
    const char *state_str;

    // 遍历所有内核进程
    for_each_process(task) {
        if (task->pid == 0) {
            switch (task->state) {
                case TASK_RUNNING:          state_str = "TASK_RUNNING"; break;
                case TASK_INTERRUPTIBLE:    state_str = "TASK_INTERRUPTIBLE"; break;
                case TASK_UNINTERRUPTIBLE:  state_str = "TASK_UNINTERRUPTIBLE"; break;
                case __TASK_STOPPED:        state_str = "__TASK_STOPPED"; break;
                case __TASK_TRACED:         state_str = "__TASK_TRACED"; break;
                default:                    state_str = "UNKNOWN"; break;
            }
            printk(KERN_INFO "init_task PID: %d, state: %s\n", task->pid, state_str);
            break;
        }
    }
}

// 模块入口、出口函数同方法1
module_init(mymodule_init);
module_exit(mymodule_exit);
MODULE_LICENSE("GPL");

注意事项

  • 访问task_struct时需注意进程上下文,禁止在原子上下文(如中断处理函数)中遍历进程列表。
  • 不同内核版本的进程状态宏定义可能略有差异,建议参考对应版本的linux/sched.h头文件。
  • 模块必须声明MODULE_LICENSE("GPL"),否则可能无法访问init_task等GPL-only的内核导出符号。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 04:15:37