一、linux kernel源码阅读方案的组成

  1. vim。(推荐7以上版本即可)
  2. cscope。C语言源代码索引工具。用它可以生成源代码索引,并在vim中使用索引,还可以直接在命令行使用索引。

为什么没提到ctags?ctags是比scope更常用的源代码索引工具。用它也可以生成源代码索引,并在vim中使用索引。
但是,一般用ctags只是为了ctrl+]跳转到函数定义,而这在vim中输入命令set cscopetag来实现,所以其实可以不装ctags。
当然,可以两个都使用,也没多费事。

这个方案的特点就是轻量级,方便快捷。
几乎所有的linux发行版都有这些工具,可以随时搭建。
还有一点就是,它基本够用。

二、方案的搭建

工具安装

我以centos7.9为例

  1. vim。 系统自带,不用安装。
  2. ctags。一般系统默认软件仓库就有。sudo yum -y install ctags ,即可拥有。
  3. cscope。一般系统默认软件仓库就有。sudo yum -y install cscope ,即可拥有。

kernel源码索引的创建

创建以下脚本

#!/bin/bash

CWD=`pwd`
TMPFILE=${CWD}/cscope.files

# gen the cscope.out file
find $CWD -name "*.[chxsS]" -o \( -path "${CWD}/Documentation*" -a -type f \) > $TMPFILE
cscope -b -k -q
rm -f $TMPFILE

我这个脚本使了两个花招:

  1. 通过find命令,让cscope生成的索引都是全路径。好处是日后想要把索引文件挪到别的地方也是可行。
  2. 通过find命令,只挑选了我感兴趣的文件生成索引。

这样,只要去到源码目录,然后运行本脚本就可以生成cscope索引了。

csccope的索引文件

cscope生成的索引文件有下面三个。

  1. cscope.out
  2. cscope.in.out
  3. cscope.po.out

其实只需一个cscope.out就可以运行,其余两个是为了加快查找速度的,但以目前的电脑的配置,相差也不大。如果不想多两个文件污染目录,可以在上面的脚本的cscope命令中去掉-q。

三、cscope基本使用

最基本的办法是cscope -d进入界面。
cscope -d界面

ctrl+d : 退出界面
ctrl+n/p : 在上面Find XXX各条目中上下移动。输入要查找的字符,按回车可得结果。
tab : 从搜索结果中返回到下面的Find XXX条目

四、在vim中使用cscope

首先要配置一下,把下面文件的内容复制粘贴到你的~/.vimrc
https://cscope.sourceforge.net/cscope_maps.vim

打开vim就会自动加载cscope.out索引文件了。
另外,上面的文件内容建议你看看,它就定义了几条命令,对应上面cscope界面的各种搜索。
比如cs f g submit_bio命令,就是搜索submit_bio()的定义
此文件还帮你定义了相应的快捷键,比如ctrl+\ g 就是搜索光标当前的词的定义

此文件还会帮你做set cscopetag这个事,使得没有ctags也可以正常使用ctrl+]

命令:cs show 可以查看当前连接上的cscope.out文件

如果你的vim已经会自动加载cscope.out文件,那么加载.vimrc的时候就会报告重复加载的错误,这时只需把下面几行注释掉即可。

    " " add any cscope database in current directory
    " if filereadable("cscope.out")
    "     cs add cscope.out  
    " " else add the database pointed to by environment variable 
    " elseif $CSCOPE_DB != ""
    "     cs add $CSCOPE_DB
    " endif

五、vim+cscope的使用

很多人不能坚持使用,总想换到更现代的ide,是因为无法使用这些老工具完成工作。
下面来看看在具体的阅读源码场景中如何使用vim+cscope。

运行cscope -d

使用cscope,从运行cscope -d开始。很多时候,我们都是查函数,并不知道这个函数在什么文件,这时候使用cscope -d真是很方便。
由于cscope -d的界面直观,毋庸赘述,下面的例子则默认是在vim里面使用cscope。

查找函数定义

方法一:命令cs f g submit_bio
方法二:光标停在单词submit_bio上,按ctrl+\ g,在当前窗口跳转到函数定义
方法三:光标停在单词submit_bio上,按ctrl+space g,上下分割窗口并跳转到函数定义
方法四:光标停在单词submit_bio上,按ctrl+space ctrl+space g,左右分割窗口并跳转到函数定义

查找函数被调用的地方

像上面一样有4种方法,只列一种: cs f c submit_bio

在某个目录中查找

我只想查找xfs模块中调用submit_bio的地方:
grep -r -F submit_bio fs/xfs
注意,这命令是按下:之后马上输入,并不是:!grep -r -F submit_bio fs/xfs
这命令会把grep的结果放入quickfix
熟悉quickfix窗口的操作可以方便快捷跳转到每一行,如果不熟悉,就要去熟悉啦。

在特定文件中找

我只想看看有无.h文件用到submit_bio,可以这样
grep -r -F submit_bio --include=*.h *

查看当前所在文件全路径

normal模式下:1 ctrl+g (即先按1再按ctrl+g)

使用netrw浏览打开文件的路径

命令Vexplore : 打开一个左侧窗口,显示netrw文件浏览器,并定位到当前文件的目录

如果你不熟悉vim的多窗口操作,就要去熟悉啦
如果你不熟悉netrw的操作,就要去熟悉啦

查找文件

方法一:可以使用vim自带的插件netrw
方法二:cs f f xfs_buf ,查找文件名匹配xfs_buf的文件

查找syscall定义

内核的syscall定义是这样的
SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag)
要想找到它,就要使用正则表达式匹配
命令 cs f e SYSCALL.*unlink 就可以找到它

要搜索的东西带空格

不用带额外的引号,直接搜就好
cs f e error = -EBADF

要搜索的东西带-前缀

你在linux命令行试过grep带-前缀的单词吗?
比如 grep -r "-ENOMEM"这样,你会得到报错

[zp001@mycentos79 linux-3.10.0-1160.el7]$ grep -r "-ENOMEM" 
grep: invalid option -- 'N'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.

解决办法是grep -r -- "-ENOMEM"
--的意思是告诉bash,我已经输入完了命令参数了,后面的字符请不要解释成命令参数
在cscope命令中,则好办,因为它根本没这个问题
cs f e -ENOMEM

在当前文件里搜索某个关键字

其实这个需求蛮常见的,比如我找到这个unlinkat函数,它调用了do_unlinkat。
凭直觉就感觉到,在本文件内,do_unlinkat应该会被多次用到,我要怎么把它们都找出来呢?

SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag)
{
	if ((flag & ~AT_REMOVEDIR) != 0)
		return -EINVAL;

	if (flag & AT_REMOVEDIR)
		return do_rmdir(dfd, pathname);

	return do_unlinkat(dfd, pathname);
}

答案是
vim do_unlinkat %
vim是vimgrep命令的缩写,它会找到所有包含do_unlinkat的行,并输入到quickfix窗口
%代表当前文件

vim不支持系统粘贴板怎么办

很多时候,我们要把找到的函数copy出来,如果vim不支持系统粘贴板真是抓狂。
网上很多方法,但是,真正能根本解决的,是重新编译vim。编译vim其实不算难,当然,如果在老系统会稍麻烦些,但是还是可以做到的。
如果不想编译,有个变通的办法,就是使用gvim。
EDITOR=gvim cscope -d
这样就可以用gvim来使用cscope,也是挺方便。

六、写在最后

这些工具和技巧算得上老手艺了,我是个怀旧的人,总是对这些老技术有莫名的喜欢。
虽然我也有一个配置得花花绿绿的neovim,但面对传统的kernel查源码工作,我还是会切换回最纯粹的vim+cscope,体验一下过去年代的便与不便。

Logo

一起探索未来云端世界的核心,云原生技术专区带您领略创新、高效和可扩展的云计算解决方案,引领您在数字化时代的成功之路。

更多推荐