游乐游手机版
首页/AI热点日报/热点详情

ChatGPT编写Linux内核模块实战教程

类型:热点整理2026-07-18
最近看到一篇文章,作者让 ChatGPT 写一个内核模块,要求很简单:每 5 秒往控制台打印一句 "Hello world ",还得把编译用的 Makefile 一并生成。结果 AI 交出的第一版代码是这样的——创建一个内核线程,主循环每隔 1 毫秒检查一次时间,看是否过了 5 秒: while (!

最近看到一篇文章,作者让 ChatGPT 写一个内核模块,要求很简单:每 5 秒往控制台打印一句 "Hello world",还得把编译用的 Makefile 一并生成。结果 AI 交出的第一版代码是这样的——创建一个内核线程,主循环每隔 1 毫秒检查一次时间,看是否过了 5 秒:

while (!kthread_should_stop()){
    unsigned long time_since_load = jiffies - jiffies_at_load;
    unsigned long time_since_load_sec = time_since_load / HZ;
    if (time_since_load_sec >= 5)
    {
        printk(KERN_INFO "Hello world!");
        jiffies_at_load = jiffies;
    }
    // Sleep for 1 ms to a void hogging the CPU
    msleep(1);
}

这里用 msleep(1) 本身没毛病,确实能通过睡眠让出 CPU,不至于像 busy loop 里的 mdelay() 那样死占着。但问题在于,1 毫秒检查一次,5 秒内要查 5000 次,虽说没“霸占”CPU,可对资源的浪费依然不小。

接着作者让 AI 改一版,减少 CPU 消耗。AI 给出了这样的方案:

while (!kthread_should_stop()){
    printk(KERN_INFO "Hello world!");
    // Sleep for 5 seconds to a void hogging the CPU
    schedule_timeout(HZ * 5);
}

看起来问题解决了,但编译一跑,好家伙——"Hello world" 像机关枪一样往外突突,根本不是 5 秒一次。把这个问题反馈给 AI 后,它立马调整,加了一句对进程状态的设置,就正常了:

set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ * 5);

翻翻 Linux 源码,schedule_timeout() 最终会调用 __schedule(),它对进程切换的判断逻辑是这样的:

if (!preempt && prev->state)
    deactivate_task(rq, prev, ...);

TASK_RUNNING 的定义是 0x0000,所以如果之前的状态是 RUNNING,进程并不会真正从 CPU 的 runqueue 中移除——那当然就一直跑,一直框框地打印。

livegrep 上查了下 schedule_timeout() 在内核中的使用情况,发现很多代码里对 set_current_state() 设为 INTERRUPTIBLE 的语句并没有和 schedule_timeout() 紧挨着写,所以 AI“理解”不了这两者的关联,倒也情有可原。

不过 Linux 其实提供了一个“二合一”的封装函数:

sched schedule_timeout_uninterruptible(signed long timeout)
{
    set_current_state(TASK_UNINTERRUPTIBLE);
    return schedule_timeout(timeout);
}

它还有个更上层的封装——msleep(如果希望可被信号打断,就用 msleep_interruptible):

void msleep(unsigned int msecs)
{
    unsigned long timeout = msecs_to_jiffies(msecs) + 1;
    while (timeout)
        timeout = schedule_timeout_uninterruptible(timeout);
}

绕了一大圈,其实一开始直接用 msleep(5000) 最省事。

后来文章作者又提出了内核模块开发中两个很常见的需求:一是把 5 秒间隔做成模块参数(module parameter),方便动态调整,这个任务 AI 顺利完成了;二是在 /proc 文件系统里加上打印次数的统计功能,方便查询——这里出了点小插曲,AI 用了 file_operations,而不是 proc_ops,这在 5.7 及以上版本的内核里是编译不过的(类似案例可以参看另一篇文章)。不过也不能全怪 AI,没指定内核版本,它只好猜。

小结

文章作者最后写道,这次体验可以用“half amazing and half terrifying”来形容——虽然 AI 中途犯了不少错,但总比自己现查资料来得快。

除此之外,还有两点感受:一是 ChatGPT 即使出错,回答得也总是那么自信(还好不是“那么普通,却那么自信”……);二是它写的注释一条条都特别规范,连每个头文件为什么加都有理有据,这一点就强过很多人。

#include   // Needed for all kernel modules
#include   // Needed for KERN_INFO
#include     // Needed for the macros
#include  // Needed for jiffies
#include    // Needed for msleep

也有人在 ChatGPT 上试了同样的题目,得出了不太一样的结果——欲知后续,请看下文分解。

补充(为了避免影响主线剧情):schedule_timeout() 返回时,需要手动将状态设回 TASK_RUNNING 吗?不需要,因为 timer 的 callback 在唤醒进程后会将其状态自动设为 RUNNING(参考 Linux 中的等待队列机制):

void process_timeout(struct timer_list *t)
{
    struct process_timer *timeout = from_timer(timeout, t, timer);
    wake_up_process(timeout->task);
}
来源:https://m.elecfans.com/article/2215430.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。