使用vim+cscope阅读内核源码详解
方法一:命令方法二:光标停在单词submit_bio上,按ctrl+\ g,在当前窗口跳转到函数定义方法三:光标停在单词submit_bio上,按,上下分割窗口并跳转到函数定义方法四:光标停在单词submit_bio上,按,左右分割窗口并跳转到函数定义内核的syscall定义是这样的要想找到它,就要使用正则表达式匹配命令就可以找到它这些工具和技巧算得上老手艺了,我是个怀旧的人,总是对这些老技术有莫
一、linux kernel源码阅读方案的组成
- vim。(推荐7以上版本即可)
- cscope。C语言源代码索引工具。用它可以生成源代码索引,并在vim中使用索引,还可以直接在命令行使用索引。
为什么没提到ctags?ctags是比scope更常用的源代码索引工具。用它也可以生成源代码索引,并在vim中使用索引。
但是,一般用ctags只是为了ctrl+]跳转到函数定义,而这在vim中输入命令set cscopetag
来实现,所以其实可以不装ctags。
当然,可以两个都使用,也没多费事。
这个方案的特点就是轻量级,方便快捷。
几乎所有的linux发行版都有这些工具,可以随时搭建。
还有一点就是,它基本够用。
二、方案的搭建
工具安装
我以centos7.9为例
- vim。 系统自带,不用安装。
- ctags。一般系统默认软件仓库就有。
sudo yum -y install ctags
,即可拥有。 - 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
我这个脚本使了两个花招:
- 通过find命令,让cscope生成的索引都是全路径。好处是日后想要把索引文件挪到别的地方也是可行。
- 通过find命令,只挑选了我感兴趣的文件生成索引。
这样,只要去到源码目录,然后运行本脚本就可以生成cscope索引了。
csccope的索引文件
cscope生成的索引文件有下面三个。
- cscope.out
- cscope.in.out
- cscope.po.out
其实只需一个cscope.out就可以运行,其余两个是为了加快查找速度的,但以目前的电脑的配置,相差也不大。如果不想多两个文件污染目录,可以在上面的脚本的cscope命令中去掉-q。
三、cscope基本使用
最基本的办法是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,体验一下过去年代的便与不便。
更多推荐
所有评论(0)