做了这么多年开发,感觉内核这块还是最欠缺的,可能是因为内核太过于庞大复杂,加之投入时间不够,导致学习的很多东西都是零散的,难以成系统,不少内容也因为此原因,学完就忘了,最终产生踩在半空中的感觉。
最近听了不少直播课,发现差距还是挺大,而且大家都是挤时间来学习内核,这再次触动了内心深处的脆弱神经,决定还是长期投入,坚持下去。而且现在资料这么容易获取,又不是想学没资料,没有理由不坚持。
关于内核的学习,前面也提到了,既庞大又复杂,所以,成系统的掌握,需要时间的投入,也需要一些方法,否则,很容易学完就忘。
初步思考了一下,规划一下学习路径:
1 通过相关书籍,系统的了解内核。大的框架通过书本来建立。
2 带着问题学习。这样效果会比较好,也是对抗学了就忘的一种手段。
3 细节看代码。
4 要有个人的思考和理解,这也是对抗遗忘的手段。只有自己理解掌握了,内化于心,才能手到擒来。
如果出现不容易理解的地方,有一种辅助方法,就是查看最终的汇编代码。很多时候我们认为汇编比较晦涩难懂,但是这并不完全正确,有些难以理解的上层处理,很可能通过汇编反而更容易理解。
5 学习过程中先抓主线。代码里肯定会存在很多异常或者特殊处理的逻辑,陷入这些地方,容易看不到整体。
6 对流程的跟踪,可以有以下一些方法:
6.1 通过添加日志获取
6.2 通过调试获取,比如断点
6.3 通过一些接口,比如WARN_ON触发调用栈
6.4 通过Kprobe添加追踪信息
6.5 通过Ftrace查看调用信息
6.6 通过bpf相关手段查看调用信息
总的来讲,就是一边调,一边学。
内核周边的一些东西也需要了解,包括
1 打包构成
2 system map及kallsym符号表
3 与应用的衔接,比如根文件系统,init程序
4 内核跟应用代码的不同之处,不限于特权限制、竞争抢占、代码风格、支持库等
最近整理的一份学习路线,后续不断补充(这也是对嵌入式开发专栏中有关硬件和操作系统部分的深度补充):
1 搭建学习调试环境
2 内核任务框架
3 内核中各种栈,上下文
4 原子操作、锁、每CPU变量、RCU
5 中断异常
6 系统调用
7 Cache及相关
8 GDB/Kprobe/ftrace/bpf等相关内容
9 设备树