0
内核模块是用 Makefile 作为编译系统的,而 vscode 并不能自动从 Makefile 里读取出需要的信息,所以需要我们手动在 .vscode
目录下写一些配置文件,才能愉快的用 vsc 工作。
用 vscode 打开一个包含内核模块源码的目录,我们会看到
检测到 #include 错误。请更新 includePath。已为此翻译单元(/home/rapiz/Source/linux-dev/hello-world-module/hello.c)禁用波形曲线。C/C++(1696)
无法打开 源 文件 “linux/init.h”C/C++(1696)
同时自动补全也基本不可用。
这是因为没有配置正确的 includePath,vscode 找不到头文件,自然也没法补全相应的定义。
1
为了正常开发内核模块,我们至少需要 include 两个东西:
- Linux 源码中的一般头文件
内核源码根目录/include/linux
- Linux 源码中的与架构相关的头文件
内核源码根目录/arch/架构名/include
注意,这里的源码根目录不一定就是编译时使用的源码目录。编译内核模块时我们仍然是在终端里使用 Makefile 手动编译,内核源码目录是我们任意指定的。这里 vscode 配置的内核源码目录仅仅是提供给 vscode 进行扫描来自动补全和代码检查的,所以和编译时用的源码不一样问题不大。
为什么要说这个呢,因为源里会有内核的源码包,安装之后是固定位置的,只要版本和我们期望编译的版本差距不大,我们可以一直用这个固定位置的源码,比较方便。
比如 Arch Linux 安装 linux-header
后,源码跟目录就是 /usr/src/linux
。
下文就以 x86 64 位 Arch 从源里安装内核源码的情景为例。
- Linux 源码中的一般头文件
/usr/src/linux/include
- Linux 源码中的与架构相关的头文件
/usr/src/linux/arch/x86/include
虽然是 64 位的 Arch Linux,但用的路径名字是 x86
,并且我也找不到 x86_64
这个目录。不太清楚具体命名规则,反正能用。
2
但是,这样配置了 includePath 之后,我们还会报错。
检测到 #include 错误。请更新 includePath。已为此翻译单元(/home/rapiz/Source/linux-dev/task05/hello.c)禁用波形曲线。C/C++(1696)
无法打开 源 文件 “asm/rwonce.h” (dependency of “linux/init.h”)C/C++(1696)
所以我就去找了下 rwonce.h
在哪,结果是 /usr/src/linux/arch/x86/include/generated
的 asm
目录下。所以我们还需要 include /usr/src/linux/arch/x86/include/generated
此时我们需要 include 的有三样:臭豆腐,腐乳,韭菜花
/usr/src/linux/include
/usr/src/linux/arch/x86/include
/usr/src/linux/arch/x86/include/generated
3
知道了需要包含的路径,接下来我们就来具体配置 vscode。
vscode 中Ctrl
+ Shift
+ P
调出命令面板,输入 edit 应该就能搜到 C/C++: 编辑配置,这里选择 UI 或者 JSON 方式都行。UI 模式下找到包含路径选项,添加刚刚给出的三个包含路径。JSON 模式可以参考在文末给出的我的配置。
4
然而,竟然还有问题。MODULE_AUTHOR
MODULE_LICENSE
MODULE_DESCRIPTION
这种宏会被标红,提示 KBUILD_MODNAME 未定义之类的问题。
搜索了一下,KBUILD_MODNAME 是在编译时 Makefile 自动定义的宏。还好 vscode 可以在检查错误时预定义宏。在刚刚的设置页面,我们随便起个名字,定义一下 KBUILD_MODNAME="mod_hello"
。这样就好了。注意,这里的配置也是只影响 vscode 的分析引擎,对编译过程没有影响。
搜了一下还需要定义 __KERNEL__
和 MODULE
,没有去实验有什么影响,反正我加上了。
5
这样就可以愉快的在补全和错误提示下进行内核开发了。
我的 vscode 配置(.vscode/c_cpp_properites.json
),只需要看 includePath
和 defines
。
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/src/linux/include",
"/usr/src/linux/arch/x86/include",
"/usr/src/linux/arch/x86/include/generated"
],
"defines": [
"__KERNEL__=1",
"KBUILD_MODNAME=\"mod_hello\"",
"MODULE=1"
]
}
],
"version": 4
}