让ChatGPT写一个内核模块

笔者最近看到这样一篇文章  ,原作者让 chatgpt 写一个内核模块,要求实现的功能是:每 5 秒向控制台打印一句 hello world,并且把编译需要的 makefile 也一起写出来。
ai 最开始的实现方法是:创建一个内核线程,线程主体是一个 while 循环,每隔 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 avoid hogging the cpu msleep(1);}  
此处用 msleep(1) 是没有大毛病的,它确实可以通过睡眠暂时让出 cpu,避免 hogging,不像 busy loop 的 mdelay()。
但它这里实现的比较曲折,1 毫秒检查一次,5 秒内就要检查 5000 次,虽然没有「霸占」cpu,但是对 cpu 资源也是不小的浪费。
于是原作者让它改了一个更减少 cpu 消耗的版本出来:
while (!kthread_should_stop()){ printk(kern_info hello world!); // sleep for 5 seconds to avoid hogging the cpu schedule_timeout(hz * 5);}  
看起来是解决了原来存在的问题,但编译出来一试,好家伙,hello world 是突突地往控制台上打啊,根本不是间隔5 秒一次。
把这个问题反馈给 ai 后,它立马做出了调整,加入了一句对 process 状态的设置后,就可以 work 了。
set_current_state(task_interruptible);schedule_timeout(hz * 5);  
查阅 linux 源码可知,schedule_timeout() 最终会调用 __schedule() 函数,其对 process 切换的判断是这样的:
if (!preempt && prev->state) deactivate_task(rq, prev, ...);  
再由于:
#define task_running 0x0000  
所以如果之前的状态是 running,process 并不会真的离开 cpu 的 runqueue,岂不就是一直执行,一直框框地打印么。
在 https://livegrep.com/search/linux 上查了下 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(以供动态调整),这个任务被顺利完成了。
二是在 /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 在唤醒 process 后会将其状态(自动)设为 running(参考 linux 中的等待队列机制 ):
void process_timeout(struct timer_list *t){ struct process_timer *timeout = from_timer(timeout, t, timer); wake_up_process(timeout->task);}  


基于3D打印压电元件驱动的超声换能器的高能量输出应用
基于跨导运算放大器的可变带宽低通滤波器设计
一名工程师的辛酸经历
飞马F300在大面积实景三维模型生产中的应用
柔性显示市场前景可观 2020年规模可达420亿
让ChatGPT写一个内核模块
工业互联网平台能够实现数字化重塑的思考
索尼精神再展现!索尼新品4K电视为你带来更好的试听体验
运放电路—虚短虚断介绍
关于ETAS和LABCAR系统
苹果13pro和12pro的区别
Nordic将出席2024年消费电子展,展示无线物联网创新全貌
信科移动募资40亿跟进5G系统设备技术迭代升级
比亚迪汉EV车型新官图公布 有望于2020年第三季度正式上市
一加9 Pro联合哈苏共同设计影像系统
英特尔10nm处理器Windows 10任务管理器出现识别错误
关于RFID抗金属标签打印机的简介
iphone8什么时候上市?iphone8最新消息:苹果home键终于消失了,这次是iPad,iPhone8快了
图解直流电机,直流电机电机结构模型与纵向剖视图图解
高速自动测试设备的未来