注意:这篇文章上次更新于612天前,文章内容可能已经过时。
This article was last updated612 days ago, the content may be outdated.


系列教程
本文记录了如何使用 VScode 调试 Linux Kernel, 环境继承自系列教程:
安装 VScode 及其插件
从 VScode 官网 下载安装 VScode。
然后安装 C/C++ 插件,当然也可以把 C/C++ Extension Pack 也一起安装了。

生成并配置 compile_commands.json
在默认情况下使用 VScode 打开 Linux Kernel 项目,是无法自动补全的,因为 Linux Kernel 项目是使用 Makefile 进行编译的,而 VScode 默认是使用 compile_commands.json 文件进行补全的。
1 | # 使用 VScode 打开 Linux Kernel 项目 |
在默认情况下,可以看到 VScode 给出很多关于代码的错误提示,这是因为 VScode 缺少 compile_commands.json 配置文件。

在 Linux 项目中已经提供了一个脚本用于生成 compile_commands.json 文件,我们需要在 Linux 项目根目录下执行以下命令:
执行这个命令之前,请确保你已经编译过一遍 Linux Kernel 项目。
1 | # 生成 compile_commands.json |
执行完毕后,可以看到 Linux 项目根目录下多了一个 compile_commands.json 文件。
接下来我们需要在 VScode 中配置 compile_commands.json 文件,首先按快捷键 Ctrl + Shift + P 打开命令面板,输入 C/C++: Edit Configurations (JSON),然后选择 C/C++: Edit Configurations (JSON)。

它会默认在 .vscode 目录下生成一个 c_cpp_properties.json 文件,文件内容默认如下:

我们需要在这个文件中添加一行配置,指定 compile_commands.json 文件的路径:
1 | "compileCommands": "${workspaceFolder}/compile_commands.json" |
修改后的文件内容如下:

保存文件后,重启 VScode,这时候再次打开 Linux Kernel 项目,就看不到错误提示了。

配置 launch.json
接下来我们需要配置 launch.json 文件,用于调试 Linux Kernel。
点击左侧的调试按钮,快捷键 Ctrl + Shift + D,然后点击 create a launch.json file。

此时,.vscode 目录下会生成一个默认的 launch.json 文件,文件内容如下:
1 | { |

然后点击右下角的 Add Configuration,选择 C/C++: GDB(启动)。

此时,launch.json 会生成默认的内容,如下图

将 launch.json 修改为如下内容:
1 | { |
实际上仅作了如下 4 处修改

这里简单解释一下 launch.json 的配置:
name:配置名称type:调试器类型request:请求类型program:调试的程序args:调试程序的参数stopAtEntry:是否在程序入口处停止cwd:工作目录environment:环境变量externalConsole:是否使用外部控制台MIMode:调试器类型miDebuggerServerAddress:调试器地址setupCommands:设置命令
调试 Linux Kernel
准备工作已经全部完成,接下来我们就可以开始调试 Linux Kernel 了。
首先,我们在 start_kernel 处打一个断点,然后在 VScode 的终端中切换到用于启动内核镜像的目录下,执行 make run 来启动内核。
然后点击 开始调试 按钮,或者按 F5 键,就可以开始调试了。
此处内容继承自 GDB 调试 Linux Kernel

此时,我们可以看到 VScode 已经连接到了 QEMU 的 GDB 服务器,并且停在了 start_kernel 处。
我们可以使用 VScode 的调试工具栏来进行调试,比如单步调试、继续执行、查看变量、查看寄存器、查看断点、查看调用栈等。

至此,我们已经成功使用 VScode 调试 Linux Kernel 了。
接下来,我们尝试调试一下我们自己添加的系统调用,虽然只有一行代码。
在 sys.c 文件中的我们自己写的系统调用处打一个断点,然后点击 Continue 继续执行。

此时,我们在终端中执行我们写的系统调用测试程序,就可以看到 VScode 已经停在了我们自己写的系统调用处。

做一些简单的调试,你就能发现系统调用的执行流程了。
悲催的是,即使这样,你也需要更多的资料来帮助你理解 Linux Kernel。
Tutorial Series
This article records how to debug the Linux kernel with VSCode. The environment is inherited from the tutorial series:
- Linux Kernel: From Compilation to Running
- Adding a System Call to the Linux Kernel
- Writing a Module for the Linux Kernel
- Debugging the Linux Kernel with GDB
Installing VSCode and Its Extensions
Download and install VSCode from the VSCode official website.
Then install the C/C++ extension — you can also install the C/C++ Extension Pack together.

Generating and Configuring compile_commands.json
By default, opening the Linux Kernel project with VSCode won’t give you auto-completion, because the Linux Kernel project is compiled with Makefiles, while VSCode uses the compile_commands.json file for completion by default.
1 | # Open the Linux Kernel project with VSCode |
By default, you’ll see VSCode showing many code error hints, because VSCode lacks the compile_commands.json config file.

The Linux project already provides a script to generate the compile_commands.json file. We need to run the following command in the Linux project root:
Before running this command, make sure you have already compiled the Linux Kernel project once.
1 | # Generate compile_commands.json |
After it finishes, you’ll see an extra compile_commands.json file in the Linux project root.
Next, we need to configure the compile_commands.json file in VSCode. First press Ctrl + Shift + P to open the command palette, type C/C++: Edit Configurations (JSON), then select C/C++: Edit Configurations (JSON).

It will generate a c_cpp_properties.json file in the .vscode directory by default, with content like:

We need to add one line to this file, specifying the path of the compile_commands.json file:
1 | "compileCommands": "${workspaceFolder}/compile_commands.json" |
The modified file content is as follows:

After saving the file, restart VSCode. When you open the Linux Kernel project again, the error hints are gone.

Configuring launch.json
Next, we need to configure the launch.json file for debugging the Linux Kernel.
Click the debug button on the left (shortcut Ctrl + Shift + D), then click create a launch.json file.

At this point, a default launch.json file is generated in the .vscode directory, with content:
1 | { |

Then click Add Configuration in the bottom right, and select C/C++: GDB(启动).

Now launch.json will be generated with default content, as shown:

Modify launch.json to the following:
1 | { |
Actually, only the following 4 places were modified

Here’s a brief explanation of the launch.json configuration:
name: configuration nametype: debugger typerequest: request typeprogram: the program being debuggedargs: arguments for the debugged programstopAtEntry: whether to stop at the program entrycwd: working directoryenvironment: environment variablesexternalConsole: whether to use an external consoleMIMode: debugger typemiDebuggerServerAddress: debugger addresssetupCommands: setup commands
Debugging the Linux Kernel
All the preparation is done; now we can start debugging the Linux Kernel.
First, set a breakpoint at start_kernel, then in VSCode’s terminal switch to the directory used to boot the kernel image and run make run to boot the kernel.
Then click the Start Debugging button, or press F5, to start debugging.
This part is inherited from Debugging the Linux Kernel with GDB

At this point, we can see VSCode has connected to QEMU’s GDB server and stopped at start_kernel.
We can use VSCode’s debug toolbar for debugging — step over, continue, inspect variables, registers, breakpoints, call stack, etc.

At this point, we have successfully debugged the Linux Kernel with VSCode.
Next, let’s try debugging the system call we added ourselves, even though it’s just one line of code.
Set a breakpoint at our system call in sys.c, then click Continue to resume execution.

Now run our system call test program in the terminal, and you’ll see VSCode stops at our system call.

Do some simple debugging and you’ll discover the system call’s execution flow.
Unfortunately, even so, you’ll need more resources to help you understand the Linux Kernel.


