Linux学习笔记:老版本内核的坑,新工具救场,代码门道藏着啥秘密.
最近想学Linux内核,网上查资料发现现在的稳定版本都已经到5.x了,但我跟着教程选的是2.6.34。官网下载链接卡着老卡,后来用清华那个镜像站才下成功,tar解压命令输了好几回才记熟。在线看代码倒是方便,在elixir那个网站能找对应版本,不过翻来翻去感觉目录结构特别乱。
开始以为内核代码就是一堆.c文件随便放,结果打开目录发现分类特别细致。文档放在Documentation文件夹里,架构相关的代码都在arch下面,驱动全塞在drivers里。block是磁盘读写的,mm是内存管理的,kernel目录看着像核心部分。但这些名字光看不知道具体干啥,得一个一个去翻注释。
下载回来编译的时候各种依赖报错,搞了半天才发现CentOS6.10的glibc太旧了,得想办法解决。虚拟机跑了好几天卡成PPT,换成VMware之后稍微快点。现在还在研究init这个目录,里面main.c应该是启动入口,但从代码到实际运行流程还是摸不着头脑。
在线工具其实挺好用,比如elixir能跨版本对比代码,把2.6和5.x的block目录一对比,就能看出API改了不少。但有些老代码的写法现在没人用了,查资料费劲。比如内存管理那块,slab分配器和伙伴系统到底是怎么配合的,看书也说不清,只能慢慢拆开看。
最近发现security目录里的Yama模块,查了下历史记录,这个安全模块是从2.6.34开始加进来的。虽然现在的内核版本早就升级了,但老版本漏洞修复记录反而更清晰。比如某些驱动的漏洞补丁,在旧代码里能找到最早怎么改的,对理解原理有帮助。
折腾这么久终于把环境搭好了,用gedit打开mm/slub.c发现全是函数调用链,完全理不出头绪。不过用gedit插件加个代码折叠功能,至少看得清楚些。网上有人说学内核得从小版本入手,但2.6的代码结构和现在差异太大,调试起来还是绕弯子。
打算先把init的引导流程画个图,看着流程图再对照代码好理解点。但发现init/main.c后面调用了太多其他模块函数,比如启动驱动的时候会跳转到drivers目录下的代码。现在才明白,原来内核代码像一棵树根,每个目录都是枝干上的分叉。
工具方面elixir网站更新了搜索功能,现在能精准找到某个函数的修改记录。比如查到mm/memory.c里的某个函数,可以看到从2.6到5.4的每次改动。这种时间线对比挺有用的,能看出开发者怎么逐步优化算法的。不过有时候改动太小,看不出啥区别。
最头疼的是编译过程,make menuconfig配置项太多,不小心改了个参数就得重编译。有次改了内核编译选项,重启之后黑屏了,折腾了半天才恢复出厂设置。现在学会每次改完配置都备份.config文件,免得重装系统。
听说用WSL跑Linux更方便,但试了下wsl2直接编译2.6内核老是报错,可能是命名空间不兼容的问题。还是老老实实用CentOS虚拟机吧,虽然卡点但起码能跑通。最近准备把block目录里的队列管理代码过一遍,看看2.6时代的IO调度策略是什么样的。