Vimconfiguration用于Linux内核开发

内核开发实际上不同于传统的C项目开发(从我看来,作为一个新手)。 所以,我总是想知道内核黑客的vimconfiguration是什么。

最重要的是,如何在VIM中导航内核源码树。我试过ctags ,但是,它工作起来非常糟糕。

有人能给我一个线索吗?

接下来是Linux内核和普通C项目的主要区别(从开发者的角度)

  • 内核是非常大的项目(所以你应该选择哪个代码来索引)
  • 它具有与体系结构相关的代码(并且一次只对一个特定的体系结构感兴趣;其他体系结构不应被索引)
  • 它有非常具体的代码风格,你应该坚持(和VIM应该被配置为相应的显示代码)
  • 它不使用C标准库,而是拥有自己类似的例程(所以你的索引工具不应该索引libc头文件)

安装索引工具

浏览内核代码,我会建议cscopectags工具。 要安装它们,运行下一个命令:

 $ sudo aptitude install cscope exuberant-ctags 

一点解释:

  • cscope :将用于导航代码(在函数之间切换等)
  • ctags :需要为Tagbar插件(将进一步讨论)和Omni completion (vim中的自动完成机制); 也可以用于导航

创建索引数据库

现在你应该索引你的内核源文件。 这里有两种方法:手动创建索引或在内核中使用可用的脚本。 如果您不确定哪种方式最适合您,我推荐使用内核脚本,因为它在后台执行了许多巧妙的技巧(如忽略未构建的源代码和在结果列表顶部移动头文件)。

但首先,为您的架构/主板配置和构建内核,因为以后可以使用构建的文件来改进索引过程。

使用scripts/tags.sh索引

内核有相当不错的脚本( scripts/tags.sh )来创建内核索引数据库。 一个应该使用make cscope并且make tags规则来创建索引,而不是直接运行该脚本。

例:

 $ make O=. SRCARCH=arm SUBARCH=omap2 COMPILED_SOURCE=1 cscope tags 

哪里

  • O=. – 使用绝对路径(如果您想要在内核目录之外加载创建的cscope / ctags索引文件(例如,用于开发树内核模块),则很有用)。 如果你想使用相对路径(即你只会在内核目录中进行开发),只需省略该参数即可
  • SRCARCH=... – 选择CPU架构进行索引。 请参阅arch/目录以供参考。 例如,如果SRCARCH=arm ,那么arch/arm/目录将被索引, arch/*目录的其余部分将被忽略
  • SUBARCH=... – 选择要建立索引的子体系结构(即板相关文件)。 例如,如果SUBARCH=omap2 ,只有arch/arm/mach-omap2/arch/arm/plat-omap/目录会被索引,其余的机器和平台将被忽略。
  • COMPILED_SOURCE=1 – 仅索引编译的文件。 你通常只对你的构建中使用的源文件感兴趣(因此编译)。 如果你想索引还没有建立的文件,只需省略此选项。
  • cscope – 制作cscope索引的规则
  • tags – 规则,使ctags指数

手动索引

内核脚本( tags.sh )可能无法正常工作(例如,当您的主板有不同的mach-omap2目录,如mach-omap2plat-omap ),或者您可能想要更多地控制索引过程。 在这种情况下,你应该手动索引内核源代码。

手动索引的见解是从这里采取的。

首先,您需要创建cscope.files文件,该文件将列出要索引的所有文件。 例如,我正在使用下一个命令来列出ARM架构( arch/arm )的文件,特别是针对OMAP平台(不包括其余平台,以便轻松导航):

 find $dir \ -path "$dir/arch*" -prune -o \ -path "$dir/tmp*" -prune -o \ -path "$dir/Documentation*" -prune -o \ -path "$dir/scripts*" -prune -o \ -path "$dir/tools*" -prune -o \ -path "$dir/include/config*" -prune -o \ -path "$dir/usr/include*" -prune -o \ -type f \ -not -name '*.mod.c' \ -name "*.[chsS]" -print > cscope.files find $dir/arch/arm \ -path "$dir/arch/arm/mach-*" -prune -o \ -path "$dir/arch/arm/plat-*" -prune -o \ -path "$dir/arch/arm/configs" -prune -o \ -path "$dir/arch/arm/kvm" -prune -o \ -path "$dir/arch/arm/xen" -prune -o \ -type f \ -not -name '*.mod.c' \ -name "*.[chsS]" -print >> cscope.files find $dir/arch/arm/mach-omap2/ \ $dir/arch/arm/plat-omap/ \ -type f \ -not -name '*.mod.c' \ -name "*.[chsS]" -print >> cscope.files 

对于x86架构( arch/x86 ),您可以使用如下所示:

 find $dir \ -path "$dir/arch*" -prune -o \ -path "$dir/tmp*" -prune -o \ -path "$dir/Documentation*" -prune -o \ -path "$dir/scripts*" -prune -o \ -path "$dir/tools*" -prune -o \ -path "$dir/include/config*" -prune -o \ -path "$dir/usr/include*" -prune -o \ -type f \ -not -name '*.mod.c' \ -name "*.[chsS]" -print > cscope.files find $dir/arch/x86 \ -path "$dir/arch/x86/configs" -prune -o \ -path "$dir/arch/x86/kvm" -prune -o \ -path "$dir/arch/x86/lguest" -prune -o \ -path "$dir/arch/x86/xen" -prune -o \ -type f \ -not -name '*.mod.c' \ -name "*.[chsS]" -print >> cscope.files 

在哪里dir变量可以有下一个值之一:

  • . :如果你只在内核源代码目录下工作, 在这种情况下,这些命令应该从内核源代码的根目录运行
  • 你的内核源代码目录的绝对路径 :如果你要开发一些树外的内核模块, 在这种情况下,脚本可以从任何地方运行

我使用第一个选项( dir=. ),因为我没有开发任何out-of-tree模块。

现在,当cscope.files文件准备就绪时,我们需要运行实际的索引:

 $ cscope -b -q -k 

其中-k参数告诉cscope不索引C标准库(因为内核不使用它)。

现在是时候创建ctags索引数据库了。 为了加速这个阶段,我们将重新使用已经创建的cscope.files

 $ ctags -L cscope.files 

好的,建立cscopectags索引数据库,你可以删除cscope.files文件,因为我们不需要它了:

 $ rm -f cscope.files 

下一个文件包含索引数据库(对于cscopectags ):

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

将它们保存在内核源码目录的根目录下。

vim插件

:进一步我展示了如何使用病原体来处理Vim插件。 但是现在Vim 8已经发布了,可以使用本地包加载来达到同样的目的。

接下来我们要为vim安装一些插件。 为了更好地掌握它,我鼓励你使用病原体插件。 它允许你只将git clone vim插件放到你的~/.vim/bundle/并保持它们的隔离,而不是混合来自~/.vim目录中不同插件的文件。

像这里描述的那样安装病原体

不要忘记做下一个东西(就像在同一个链接中描述的那样):

添加到您的vimrc

 execute pathogen#infect() 

如果你是Vim的新手,并且缺少一个vimrcvim ~/.vimrc并粘贴下面这个超级简单的例子:

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

为vim安装cscope映射

Vim已经有了cscope的支持(参见:help cscope )。 您可以使用如下命令跳转到符号或文件:cs fg kfree 。 虽然不太方便 为了加快速度,你可以使用快捷方式(所以你可以把你的光标放在某个功能上,按下一些组合键并跳转到功能)。 为了添加cscope的快捷方式,你需要获得cscope_maps.vim文件。

要使用病原体进行安装,您可以将此 repo克隆到~/.vim/bundle

 $ git clone https://github.com/joe-skb7/cscope-maps.git ~/.vim/bundle/cscope-maps 

现在,你应该能够使用快捷方式在vim中的函数和文件之间导航。 打开一些内核源文件,将你的键盘光标放在某个函数调用上,然后按Ctrl + \,然后按g 。 它应该带给你的功能实现。 或者它可以显示所有可用的功能实现,那么你可以选择使用哪一个: cscope的-结构

对于其他键映射,请参阅cscope_maps.vim文件。

你也可以在vim中使用命令:

 :cs fg kmalloc 

有关详细信息,请参阅:help cscope

ctags注意

ctags仍然可以用于导航,例如,当寻找一些#define声明。 你可以把光标放在这个定义的用法上,然后按g然后按Ctrl + ] 。 看到这个答案的细节。

cscope说明

下一个技巧可以用来在内核中查找结构声明

 :cs ft struct device { 

请注意,上面的命令依赖于特定的struct声明样式(在内核中使用),所以我们知道struct声明总是具有这种形式: struct some_stuct { 。 这个技巧可能不适用于另一种编码风格的项目。

out-of-tree模块开发说明

如果您正在开发树型模块,您可能需要从您的内核目录加载cscopectags数据库。 它可以通过vim中的下一个命令完成(在命令模式下)。

加载外部cscope数据库:

 :cs add /path/to/your/kernel/cscope.out 

加载外部ctags数据库:

 :set tags=/path/to/your/kernel/tags 

的vimrc

为了更好地支持内核开发,还需要对~/.vimrc进行一些修改。

首先,让我们用垂直线突出第81列(因为内核编码要求你应该保持你的行长度不超过80个字符):

 " 80 characters line set colorcolumn=81 "execute "set colorcolumn=" . join(range(81,335), ',') highlight ColorColumn ctermbg=Black ctermfg=DarkRed 

如果您还想突出显示80列,请取消注释第二行。

内核编码风格禁止拖尾空格,因此您可能需要突出显示它们:

 " Highlight trailing spaces " http://vim.wikia.com/wiki/Highlight_unwanted_spaces highlight ExtraWhitespace ctermbg=red guibg=red match ExtraWhitespace /\s\+$/ autocmd BufWinEnter * match ExtraWhitespace /\s\+$/ autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/ autocmd InsertLeave * match ExtraWhitespace /\s\+$/ autocmd BufWinLeave * call clearmatches() 

内核编码风格

为了使vim尊重内核编码风格,可以使用插件: vim-linux-coding-style 。

有用的插件

下一个插件是常用的,所以你可以找到它们很有用:

  • NERDTree
  • Tagbar
  • 文件行
  • VIM航空公司

这些也是有趣的插件,但您可能需要为它们配置内核:

  • syntastic
  • YCM

全方位完成

Vim 7(及以上版本)已经内置了自动完成支持。 它称为Omni completion 。 有关详细信息,请参阅:help new-omni-completion 。

Omni完成在像kernel这样的大项目上工作起来相当缓慢。 如果你仍然需要它,你可以启用它,将下一行添加到你的~/.vimrc

 " Enable OmniCompletion " http://vim.wikia.com/wiki/Omni_completion filetype plugin on set omnifunc=syntaxcomplete#Complete " Configure menu behavior " http://vim.wikia.com/wiki/VimTip1386 set completeopt=longest,menuone inoremap <expr> <CR> pumvisible() ? "\<Cy>" : "\<Cg>u\<CR>" inoremap <expr> <Cn> pumvisible() ? '<Cn>' : \ '<Cn><Cr>=pumvisible() ? "\<lt>Down>" : ""<CR>' inoremap <expr> <M-,> pumvisible() ? '<Cn>' : \ '<Cx><Co><Cn><Cp><Cr>=pumvisible() ? "\<lt>Down>" : ""<CR>' " Use Ctrl+Space for omni-completion " https://stackoverflow.com/questions/510503/ctrlspace-for-omni-and-keyword-completion-in-vim inoremap <expr> <C-Space> pumvisible() \|\| &omnifunc == '' ? \ "\<lt>Cn>" : \ "\<lt>Cx>\<lt>Co><cr>=pumvisible() ?" . \ "\"\\<lt>cn>\\<lt>cp>\\<lt>cn>\" :" . \ "\" \\<lt>bs>\\<lt>Cn>\"\<CR>" imap <C-@> <C-Space> " Popup menu hightLight Group highlight Pmenu ctermbg=13 guibg=LightGray highlight PmenuSel ctermbg=7 guibg=DarkBlue guifg=White highlight PmenuSbar ctermbg=7 guibg=DarkGray highlight PmenuThumb guibg=Black " Enable global scope search let OmniCpp_GlobalScopeSearch = 1 " Show function parameters let OmniCpp_ShowPrototypeInAbbr = 1 " Show access information in pop-up menu let OmniCpp_ShowAccess = 1 " Auto complete after '.' let OmniCpp_MayCompleteDot = 1 " Auto complete after '->' let OmniCpp_MayCompleteArrow = 1 " Auto complete after '::' let OmniCpp_MayCompleteScope = 0 " Don't select first item in pop-up menu let OmniCpp_SelectFirstItem = 0 

并使用Ctrl + 空格来自动完成。

眼睛糖果的外观

256色

首先你要确保你的终端支持256色。 例如,可以使用urxvt-256终端来实现。 对于gnome-terminal你可以添加下一行到你的~/.bashrc

 export TERM="xterm-256color" 

一旦完成,把下一行放到~/.vimrc

 set t_Co=256 

配色方案

现在下载你喜欢的模式~/.vim/colors并在~/.vimrc选择它们:

 set background=dark colorscheme hybrid 

使用哪种配色方案是强烈的基于观点的事项。 我可能会推荐mrkn256 , 混合和日光照射的初学者。

字形

那里有很多好的字体可供编程。 Linux上的许多程序员使用Terminus字体,你可以试试它的初学者。

已知的缺点

有些功能在vim中仍然缺失。

  1. cscope / ctags不能使用include/generated/autoconf.h定义,而忽略那些没有构建的代码。 编码时将所有代码编入索引以作为参考仍然是有用的。
  2. 没有宏扩展(好吧,那里一些功能 (基于gcc -E ),但我不知道它是否会为内核工作)。

我知道唯一处理这些问题的IDE是Eclipse和CDT 。