知识分享:一文教你如何优雅的阅读linux内核源码
首先,我目前见到的最常见的编辑器是vscode和neovim,本文所介绍的方法完美适配这两个编辑器~
阅读代码的痛点
- 难以正确跳转
读代码应该都遇到过一个问题就是,有时候很多的同名函数,在编译链接的过程你不知道具体链接到了哪个,虽然vscode和neovim的ctag都有全局的搜索,但是满屏的同名函数一个一个去找,实在是不优雅~
- 对复杂的结构嵌套没有全局视角
例如如果遇到复杂的驱动,以v4l2举例,一个struct不仅包含很多个struct,而且为了减少
->
的使用,还会将里面包含的struct的一些成员提到顶层,以及还会有指向父struct(暂且这么叫)的指针,如果第一次梳理源码,这种复杂的结构会给阅读代码带来了极大麻烦
- 不同版本之间代码变动,接口弃用,但不知道原因
在版本更新的过程中,经常遇见一些情况导致以前使用的接口在新版中弃用,那么为了更好的使用新版本,就需要对搞懂这些原因
ok,uu们如果你也苦于上面的情况,希望这篇文章能帮大家更好的阅读源码~
解决方法
优雅跳转
主要使用的是compile_commands.json
这个文件,这个是clangd的lsp使用到的,其中记录了一个文件编译过程中使用到的文件,如果有这个文件,那么完成正确的跳转,就不在话下了~
- 首先需要编译linux源码,不管是clangd,还是交叉编译链都可以。
2.1 linux kernel源码,如果用clangd构建指定好LLVM还是可以使用下面的指令得到 compile_commands.json
这个文件的。
./scripts/gen_compile_commands.py
2.2 但是对于 aarch64-linux-gnu-gcc
这个交叉编译链,会生成clangd无法识别的指令,所以需要在linux kernel源码目录下
touch .clangd
并且在 .clangd
中输入下面的内容
CompileFlags:
Remove: -mabi=lp64
- 再启动lsp,就可以发现可以直接跳转啦~(vscode是clangd的插件,nvim如果使用的是lazyvim,不需要额外配置)
ps:这里使用的clangd,可能在执行过程中缺少一些程序包,apt install就好
复杂的嵌套结构可视化
原理
内核每个源文件编译会生成 .xx.o.cmd 的隐藏文件,里面包含了依赖源文件和头文件列表
如imx219.c对应的 .imx219.o.cmd 里
3 source_drivers/media/i2c/imx219.o := ~/linux/vender/nvidia/drivers/media/i2c/imx219.c
4
5 deps_drivers/media/i2c/imx219.o := \
6 $(wildcard include/config/of.h) \
7 include/linux/slab.h \
8 $(wildcard include/config/debug/slab.h) \
9 $(wildcard include/config/debug/objects.h) \
主要就是使用doxygen来生成,并且可以配合一下graph软件,生成可视化的图
步骤
- 安装软件
$ sudo -H pip3 install filetype pygraphviz
$ sudo apt-get install build-essential python3-dev libssl-dev libffi-dev libxml2 libxml2-dev libxslt1-dev zlib1g-dev
$ sudo apt-get install python3-pygraphviz
$ sudo apt-get install doxygen-latex doxygen-doc doxygen-gui graphviz
$ doxywizard //doxygen启动
配置
- 内核源码中实际编译的文件列表
//kernel_src_dump.py
#!/usr/bin/env python
import sys
import os
import os.path
import time
import re
import argparse
KERNEL_BASE = os.getcwd()
KERNEL_SRC = os.getcwd()
KERNEL_OUT = os.getcwd()
def kernel_depfile_2_flist(depfile, filelist) :
fobj = open(depfile, "r")
for line in fobj :
txt = line.strip()
if 0 == len(txt) :
continue
if txt.startswith("cmd_") :
continue
if txt.startswith("deps_") :
continue
if txt.startswith("$(deps_") :
continue
if txt.endswith(".o)") :
continue
if txt.endswith(" \\") :
txt = txt[:-2]
if txt.startswith("$(wildcard ") and txt.endswith(")"):
idx_start = len("$(wildcard ")
tmp_txt = txt[idx_start : -1]
pre_path = KERNEL_OUT
relative_path = os.path.join(pre_path, tmp_txt)
abs_path = relative_path
if KERNEL_BASE in KERNEL_OUT:
pre_path = KERNEL_OUT[len(KERNEL_BASE) +
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
1. 自我介绍:高通、Oppo(sp)、vivo(sp)、小米(ssp)、荣耀(26k*12+80k)、华子(报批中)、美团、韶音、经纬恒润、乐鑫、中兴、TP 2. 内容: 1.嵌入式学习的资料和路径 2.所有面试的题目和解答(持续更新)、对评论的快速解答 3.各种碎碎念 3.整理不易,buy me coffee☕️,为了回馈牛客和各个粉丝,文章都会先试读几天,热度过了再收录~