内核开发学习准备工作

内核版本

Linux Kernel Development (2.6.34)和 Professional Linux Kernel Architecture (2.6.24) 解析Linux版本采用的是稳定内核系列 2.6.x ,大约相当于 RHEL/CentOS 6.x 时代主流Linux发行版采用的内核版本。这个系列内核具备了现代Linux系统的特性,同时代码量尚未急剧膨胀。

我采用 CentOS 6.10 系统,然后安装 kernel v2.6 内核

备注

目前(2023年),除了学习目的采用早期稳定内核v2.6,其他体验最新技术可以选择v6.1: 2023年2月,Linux 6.1成为2022 LTS(长期支持)内核,计划维护到2026年12月,特定LTS(通常是主要行业参与者协调,如Android)可能会一直维护到2028年12月。 Linux 6.1 被选为 LTS 长期支持内核

开发环境准备

安装索引工具

在内核源代码浏览,需要使用索引工具,推荐使用 cscopectags ,以下命令进行安装:

sudo yum install cscope ctags-etags

如果是debian系统,则安装 cscope exuberant-ctags

备注

  • cscope 是用于在代码函数间转跳,可以跳到符号定义,搜索所有符号使用等

  • ctagsTagbar 插件所需要的,也是 Omni completion (vim内置的自动补全机制) 所使用等,也可以用于代码函数转跳。 不过 ctags 不如 cscope 的转跳功能,因为 ctags 只能挑到符号定义位置。

在内核源代码目录下,有2种方式可以创建索引:

  • 手工创建索引

  • 使用内核提供的脚本创建索引

如果你不知道哪种方式更适合,推荐使用内核脚本

使用 scripts/tags.sh 脚本创建索引

内核源代码提供了一个很好的脚本 scripts/tags.sh 来创建内核索引数据库,也就是使用 make cscopemake tags 规则来创建索引,类似如下:

make O=. ARCH=arm SUBARCH=omap2 COMPILED_SOURCE=1 cscope tags

这里:

  • O=. 使用绝对路径(如果你需要在内核源代码目录之外加载创建的 cscope/ctags 索引文件,例如开发 out-of-tree 内核模块)。如果你想使用相对路径(例如只在内核源代码目录下开发)就可以忽略这个参数

  • ARCH=... 选择索引的CPU架构。例如使用 ARCH=armarch/arm/ 目录将会索引,其他 arch/* 目录将被忽略

  • SUBARCH=... 选择子架构(和主办相关文件)索引。例如 SUBARCH=omap2 则只有 arch/arm/mach-omap2/arch/arm/plat-omap/ 目录被索引,其他主机和平台被忽略。

  • COMPILED_SOURCE=1 只索引编译过文件。通常只是对源代码中你编译部分索引,如果还需要所有其他不被编译的文件,就不使用这个参数

  • cscope 创建cscope索引的规则

  • tags 创建ctags索引的规则

例如,开发x86的代码:

make ARCH=x86 cscope tags

手工创建索引

内核脚本 tags.sh 有可能不能正常工作,或者你需要采用更多控制索引的功能,此时你可以手工索引内核源代码(详情可参考 Using Cscope on large projects (example: the Linux kernel) ):

  • 首先创建一个 cscope.files 文件列出所有需要索引的文件

如果是ARM架构:

howto_learn_kernel/cscope-arm.files
 1find    $dir                                          \
 2        -path "$dir/arch*"               -prune -o    \
 3        -path "$dir/tmp*"                -prune -o    \
 4        -path "$dir/Documentation*"      -prune -o    \
 5        -path "$dir/scripts*"            -prune -o    \
 6        -path "$dir/tools*"              -prune -o    \
 7        -path "$dir/include/config*"     -prune -o    \
 8        -path "$dir/usr/include*"        -prune -o    \
 9        -type f                                       \
10        -not -name '*.mod.c'                          \
11        -name "*.[chsS]" -print > cscope.files
12find    $dir/arch/arm                                 \
13        -path "$dir/arch/arm/mach-*"     -prune -o    \
14        -path "$dir/arch/arm/plat-*"     -prune -o    \
15        -path "$dir/arch/arm/configs"    -prune -o    \
16        -path "$dir/arch/arm/kvm"        -prune -o    \
17        -path "$dir/arch/arm/xen"        -prune -o    \
18        -type f                                       \
19        -not -name '*.mod.c'                          \
20        -name "*.[chsS]" -print >> cscope.files
21find    $dir/arch/arm/mach-omap2/                     \
22        $dir/arch/arm/plat-omap/                      \
23        -type f                                       \
24        -not -name '*.mod.c'                          \
25        -name "*.[chsS]" -print >> cscope.files

如果是X86架构:

howto_learn_kernel/cscope-x86.files
 1find    $dir                                          \
 2        -path "$dir/arch*"               -prune -o    \
 3        -path "$dir/tmp*"                -prune -o    \
 4        -path "$dir/Documentation*"      -prune -o    \
 5        -path "$dir/scripts*"            -prune -o    \
 6        -path "$dir/tools*"              -prune -o    \
 7        -path "$dir/include/config*"     -prune -o    \
 8        -path "$dir/usr/include*"        -prune -o    \
 9        -type f                                       \
10        -not -name '*.mod.c'                          \
11        -name "*.[chsS]" -print > cscope.files
12find    $dir/arch/x86                                 \
13        -path "$dir/arch/x86/configs"    -prune -o    \
14        -path "$dir/arch/x86/kvm"        -prune -o    \
15        -path "$dir/arch/x86/lguest"     -prune -o    \
16        -path "$dir/arch/x86/xen"        -prune -o    \
17        -type f                                       \
18        -not -name '*.mod.c'                          \
19        -name "*.[chsS]" -print >> cscope.files

这里 dir 变量有以下值:

  • . 如果直接在内核源代码目录,也就是所有命令都在源代码目录的根上执行

  • 内核源代码的绝对路径 则是在内核源代码目录外开发模块时候使用

cscope.files 文件生成后,需要运行实际索引:

cscope -b -q -k

这里参数 -k 是让 cscope 不要索引C标准库(因为kernel不使用)

  • 然后就是创建 ctags 索引数据库,这里需要重用刚才创建的 cscope.files

    ctags -L cscope.files
    
  • 在完成了 cscopectages 索引数据库创建之后,我们可以删除 cscope.files 因为不再需要这个文件:

    rm -f cscpe.files
    

以下文件位于源代码目录下包含了索引:

cscope.out
cscope.out.in
cscope.out.po
tags

vim安装

由于在内核学习过程中,使用旧版本 CentOS 6,提供的vim版本较低,所以考虑到vim插件 YouCompleteMe 对vim版本有很高要求,所以 在CentOS6上编译安装vim ,以便能够使用最新插件。后续其他开发,我准备再使用最新的CentOS或Ubuntu重新部署开发环境,并制作docker镜像方便工作学习。

vim插件

vim有多种插件管理工具,例如 pathogen (这通常是vim新手安装的第一个插件)。甚至从Vim 8开始, Vim 8原生第三方插件包加载 ,不过传统上方便独立包路径管理,还是使用插件管理工具 pathogen

  • 安装 pathoegn plugin 可以只需要使用 git clone 将vim插件下载到 ~/.vim/bundle/ 目录下:

    mkdir -p ~/.vim/autoload ~/.vim/bundle && \
    curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
    
  • 上述命令执行成功后设置运行时路径(Runtime Path Manipulation),在 ~/.vimrc 中添加:

    execute pathogen#infect()
    syntax on
    filetype plugin indent on
    

LXR Cross Referencer

LXR Cross Referencer 是源代码阅读平台,可以通过浏览器阅读代码。

参考