用于Linux内核开发的Vim配置

Dou*_* Su 22 linux vim linux-kernel

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

最重要的是如何在vim中导航内核源代码树.但我尝试过ctags,它的工作非常糟糕.

有人能给我一个线索吗?

Sam*_*nko 69

Linux内核和常规C项目之间的主要区别(从开发人员的角度来看)是下一个:

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

安装索引工具

要导航内核代码,我会建议cscopectags工具.要安装它们,请运行next命令:

$ sudo aptitude install cscope exuberant-ctags
Run Code Online (Sandbox Code Playgroud)

一点解释:

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

创建索引数据库

现在您应该索引内核源文件.这里有两种方法:手动创建索引或在内核中使用可用脚本.如果您不确定哪种方式最适合您,我建议使用内核脚本,因为它在幕后做了很多巧妙的技巧(比如忽略非构建的源代码并在结果列表的顶部移动头文件).

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

用索引编制索引 scripts/tags.sh

内核有很好的脚本(scripts/tags.sh)用于创建内核索引数据库.应该使用make cscopemake tags规则来创建索引,而不是直接运行该脚本.

例:

$ make O=. ARCH=arm SUBARCH=omap2 COMPILED_SOURCE=1 cscope tags
Run Code Online (Sandbox Code Playgroud)

哪里

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

手动索引

内核脚本(tags.sh)可能无法正常工作,或者您可能希望对索引过程有更多控制权.在这些情况下,您应手动索引内核源.

手动索引的见解来自这里.

首先,您需要创建一个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
Run Code Online (Sandbox Code Playgroud)

对于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
Run Code Online (Sandbox Code Playgroud)

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

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

我正在使用第一个选项(dir=.),因为我没有开发任何树外模块.

现在cscope.files文件准备好了,我们需要运行实际的索引:

$ cscope -b -q -k
Run Code Online (Sandbox Code Playgroud)

where -k参数告诉cscope不要索引C标准库(因为内核不使用它).

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

$ ctags -L cscope.files
Run Code Online (Sandbox Code Playgroud)

好的,cscope并且ctags构建了索引数据库,您可以删除cscope.files文件,因为我们不再需要它了:

$ rm -f cscope.files
Run Code Online (Sandbox Code Playgroud)

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

- cscope.in.out
- cscope.out
- cscope.po.out
- tags
Run Code Online (Sandbox Code Playgroud)

将它们保存在内核源目录的根目录中.

vim插件

注意:此外,我将展示如何使用病原体处理Vim插件.但是现在已经发布了Vim 8,可以使用本机程序包加载来实现相同的目的.

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

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

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

将此添加到您的vimrc:

execute pathogen#infect()
Run Code Online (Sandbox Code Playgroud)

如果你是Vim的新手并缺少一个vimrc,vim ~/.vimrc并粘贴在以下超小例子中:

execute pathogen#infect()
syntax on
filetype plugin indent on
Run Code Online (Sandbox Code Playgroud)

为vim安装cscope映射

Vim已经有了cscope支持(参见参考资料:help cscope).您可以使用类似命令跳转到符号或文件:cs f g kfree.虽然这不太方便.为了加快速度,您可以使用快捷方式(因此您可以将光标放在某个功能上,按某些组合键并跳转到功能).要为cscope添加快捷方式,您需要获取cscope_maps.vim文件.

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

$ git clone https://github.com/joe-skb7/cscope-maps.git ~/.vim/bundle/cscope-maps
Run Code Online (Sandbox Code Playgroud)

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

对于其余的键映射,请参阅cscope_maps.vim文件.

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

:cs f g kmalloc
Run Code Online (Sandbox Code Playgroud)

详情:help cscope请见.

ctags注意

ctags仍然可用于导航,例如在寻找某些#define声明时.您可以将光标放在此定义用法上,g然后按Ctrl+键].有关详情,请参阅此答案.

cscope note

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

:cs f t struct device {
Run Code Online (Sandbox Code Playgroud)

请注意,上面的命令依赖于特定的结构声明样式(在内核中使用),因此我们知道struct声明始终具有以下形式:struct some_stuct {.这个技巧可能不适用于具有其他编码风格的项目.

out-of-tree模块开发说明

如果你正在开发外的树模块,你可能会需要加载cscope,并ctags从你的内核目录数据库.它可以通过vim中的下一个命令(在命令模式下)完成.

加载外部cscope数据库:

:cs add /path/to/your/kernel/cscope.out
Run Code Online (Sandbox Code Playgroud)

加载外部ctags数据库:

:set tags=/path/to/your/kernel/tags
Run Code Online (Sandbox Code Playgroud)

的vimrc

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

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

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

如果您想要突出显示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()
Run Code Online (Sandbox Code Playgroud)

内核编码风格

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

有用的插件

下一个插件是常用的,所以你也可以发现它们很有用:

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

全方位完成

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

Omni完成在像内核这样的大项目上工作得相当慢.如果你仍然需要它,你可以启用它为你的下一行添加~/.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() ? "\<C-y>" : "\<C-g>u\<CR>"
inoremap <expr> <C-n> pumvisible() ? '<C-n>' :
  \ '<C-n><C-r>=pumvisible() ? "\<lt>Down>" : ""<CR>'
inoremap <expr> <M-,> pumvisible() ? '<C-n>' :
  \ '<C-x><C-o><C-n><C-p><C-r>=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>C-n>" :
  \ "\<lt>C-x>\<lt>C-o><c-r>=pumvisible() ?" .
  \ "\"\\<lt>c-n>\\<lt>c-p>\\<lt>c-n>\" :" .
  \ "\" \\<lt>bs>\\<lt>C-n>\"\<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
Run Code Online (Sandbox Code Playgroud)

并使用Ctrl+ Space进行自动完成.

眼睛糖果外观

256色

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

export TERM="xterm-256color"
Run Code Online (Sandbox Code Playgroud)

一旦完成,请将下一行放入~/.vimrc:

set t_Co=256
Run Code Online (Sandbox Code Playgroud)

配色方案

现在下载您喜欢的方案~/.vim/colors并选择它们~/.vimrc:

set background=dark
colorscheme hybrid
Run Code Online (Sandbox Code Playgroud)

使用哪种配色方案是基于意见的强烈问题.我可能会为初学者推荐mrkn256,混合日晒.

字形

编程有很多好的字体.Linux上的许多程序员都使用Terminus字体,你可以尝试它为初学者.

已知的缺点

vim中仍然缺少某些功能.

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

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

  • 这是一个糟糕的问题(太笼统,容易产生不同意见),但你的答案是对 vim 配置的很好的概述和介绍! (2认同)