0. 参考链接
使用VSCode进行linux内核代码阅读和开发_vscode阅读linux内核-CSDN博客
1. 搭建Linux内核源码阅读环境
现状,Linux内核源码比较庞大文件非常多,其中又包含的众多的宏定义开关配置选项,这使得阅读内核源代码称为一件头疼的事。
主要的解决防范有:
- 使用 文本浏览工具 + grep 命令来搜索内核源码,这种方式最简单,效率也最低
- 使用 SourceInsight 进行内核代码浏览,这种方式使用的人最多,但是在浏览内核源码文件时有多个硬件平台的头文件和源码配置,如果不做排除在进行符号跳转的时候往往会找到多个同名函数或定义。最重要的是 SourceInsight 是商业收费软件,需要付费购买才能使用。
- Vim + ctags ,这种方法比较高大上,但是比较适合Linux高手使用,对于初学者有可能玩不太转。
- VSCode + C++ Intellisense插件或者global插件,和SourceInsight类似,在源码符号跳转时往往会找到多个同名函数或定义。
阅读内核源码的主要痛点在于,查看一个内核函数或者宏,一个函数或宏对应着很多用 ‘#ifdef CONFIG_XXX’ 隔离起来的多个版本,并且在不同的硬件平台上又有不同的多种版本,造成我们不清楚当前开发的平台上到底使用的是哪一个内核函数版本。
新的方法
参考引用链接中的方法,可以使用 VSCode + RemoteSSH + Clangd 插件来构建内核源码阅读开发环境。其中 VSCode 作为强大的源码文本浏览编辑器,负责主题框架和显示。RemoteSSH访问远程服务器,实现远程代码的本地访问。Clangd 用于代码语义分析,代码补全,代码跳转等。该方案几乎克服了上面列出的几种方案的所有缺点,能够做到代码精准跳转,代码精准补全,其它的默认如代码颜色着色,代码缩进等都是VSCode自带的。另外,最重要的是这些是免费的。
除了 VSCode IDE 之外,该方案的核心是 Clangd 插件,clangd插件通过读取工程编译期间生成的 ompile_commands.json 文件来索引其中包含的源文件和关联的头文件,因此能避免所引导非编译代码造成的符号语义解析混乱。
compile_commands.json 文件就是由每个源文件的编译参数,路径等信息组成的一个json 文件,clangd 通过这个文件可以准确定位源文件引用的头文件从而精确的找到各种宏定义,函数,变量声明的准确值。
那么问题来了,编译内核的时候也没有生成 compile_commands.json 文件。在这文件在编译 cmake 工程的时候可以调用 cmake 命令时添加 -DMAKE_EXPORT_COMPILE_COMMANDS=on 参数,编译的时候回自动生成。但是内核使用的是make,这就需要另一个工具bear了,它就是专门用来生成这个 compile_commands.json 文件的。
在 Unbuntu 下直接使用 apt install bear 来安装 bear 工具就可以了。
sudo apt install bear
使用 bear 来生成内核编译 json 文件的方法也很简单,只需要在你平时编译内核的命令前加上 bear 就可以了,例如:
bear make ARCH=arm CROSS_COMPILE=arm-linux-gnu- zImage
2. 查看并下载需要的内核版本
当前想在 x86 32bit Ubuntu-14.04 Virtualbox 虚拟机上测试和开发Linux内核模块(驱动),所以我想阅读下当前我安装的 x86 32bit Ubuntu-14.04 Virtualbox 虚拟机内核编译使用的源码,并传入当前正在使用的virtualbox x86 32bit ubuntu-14.04 虚拟机的编译选型(宏开关),来准确的定义到需要的源码中的头文件,函数,变量的准确定义,排除同一个变量名(函数名)的多个声明。
查看我当前Ubuntu-14.04 虚拟机的内核版本:
##查看 /porc/version文件来查看当前Ubuntu-14.04 虚拟机的内核版本
dimon@dimon-VirtualBox:~$ cat /proc/version
Linux version 4.4.0-142-generic (buildd@lgw01-amd64-032) (gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4) ) #168~14.04.1-Ubuntu SMP Sat Jan 19 11:28:33 UTC 2019##使用命名 uname -r 查看当前Ubuntu-14.04 虚拟机的内核版本
dimon@dimon-VirtualBox:~$ uname -r
4.4.0-142-generic
dimon@dimon-VirtualBox:~$
可以看到当前我Ubuntu-14.04 虚拟机的内核版本是 Kernl-4.4.0-142,然后去下载对应的 kernel 内核源码包。
到 Linux 内核源码网站上下载对应的 kernel-4.4.0-142 内核源码,访问内核官方网站:
The Linux Kernel Archives
访问 kernel.org 网站,下载速率可能会比较慢(原因你懂的),我们可以到国内和内核镜像站去下载对应内核版本,例如,清华镜像站,阿里云镜像站等。如下,到清华镜像下载kernkernel-4.4.0-142 内核源码。
使用 wget 命令下载需要的内核版本
wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v4.x/linux-4.4.tar.xz
至此我需要的和我当前Virtualbox x86 32bit Ubuntu-14.04 虚拟机对应的内核源码包已经下载成功。根据你自己的虚拟机配置,也可以下载自己虚拟机Ubuntu版本对应的内核源码包。
3. 使用Clang搭建内核源码阅读环境
解压下载到的kernel-4.4.0 内核源码包。
tar -xvf linux-4.4.tar.xz
如在我上一个博文中记录的,查看当前环境中 x86 32bit Ubuntu-14.04 虚拟机虚拟机的内核编译参数。当前我Ubuntu-14.04 虚拟机内核的编译参数配置文件,存放在虚拟机的如下文件目录中。
查看当前运行Linux内核的编译参数-CSDN博客
/usr/src/linux-headers-4.4.0-142-generic/.config
我们可以使用这个当前Ubuntu-14.04 内核编译参数配置文件 '.config' 加上下载的kernel-4.4.0 源码包,来自行编译出当前虚拟机对应的内核。
我们进入之前解压的kernel-4.4.0 目录,通过内核源码来编译一下内核,如上一节提到的我们在编译命令前加上 ‘bear’ 来让内核编译时生成 compile_command.json 文件。
拷贝 '.config '内核编译配置文件到解压的内核源码目录。
## 把当前unbuntu-14.04 内核编译的配置参数文件,拷贝到我们解压的内核源码目录
cp /usr/src/linux-headers-4.4.0-142-generic/.config .
使用加上了'bear'前缀的 'make zimage' 命令来编译内核镜像。