内核开发实际上与传统的C项目开发不同(从我看来,作为一个新手)。所以,我总是想知道内核黑客的vim配置是什么。
最重要的是如何在vim中导航内核源代码树..我试过ctags
但是,它工作得非常糟糕。
有人能给我一些线索吗?
答案 0 :(得分:62)
Linux内核和常规C项目之间的主要区别(从开发人员的角度来看)是下一个:
要导航内核代码,我建议使用cscope
和ctags
工具。要安装它们,请运行下一个命令:
$ sudo aptitude install cscope exuberant-ctags
一点解释:
cscope
:将用于导航代码(在函数之间切换等)ctags
:Tagbar
插件需要(将进一步讨论)和Omni completion
(vim中的自动完成机制);也可以用于导航现在您应该索引内核源文件。这里有两种方法:手动创建索引或在内核中使用可用脚本。如果您不确定哪种方式最适合您,我建议使用内核脚本,因为它在幕后做了很多巧妙的技巧(比如忽略非构建的源代码并在结果列表的顶部移动头文件)。
但首先,为您的架构/电路板配置和构建内核,因为以后可以使用构建的文件来改进索引过程。
scripts/tags.sh
内核具有非常好的脚本(scripts/tags.sh
),用于创建内核索引数据库。应该使用make cscope
和make tags
规则来创建索引,而不是直接运行该脚本。
示例:
$ make O=. ARCH=arm SUBARCH=omap2 COMPILED_SOURCE=1 cscope tags
,其中
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
)可能无法正常工作,或者您可能希望对索引过程有更多控制权。在这些情况下,您应该手动索引内核源代码。
手动索引的见解来自here。
首先,您需要创建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=.
),因为我没有开发任何树外模块。
现在,当cscope.files
文件准备就绪时,我们需要运行实际的索引:
$ cscope -b -q -k
-k
参数告诉cscope
不要索引C标准库(因为内核不使用它)。
现在是时候创建ctags
索引数据库了。为了加速这一阶段,我们将重新使用已创建的cscope.files
:
$ ctags -L cscope.files
好的,构建了cscope
和ctags
索引数据库,您可以删除cscope.files
文件,因为我们不再需要它了:
$ rm -f cscope.files
下一个文件包含索引数据库(适用于cscope
和ctags
):
- cscope.in.out
- cscope.out
- cscope.po.out
- tags
将它们保存在内核源目录的根目录中。
注意:此外,我将展示如何使用 pathogen 来处理Vim插件。但是现在已经发布了Vim 8,可以使用native package loading来达到同样的目的。
接下来我们将为vim安装一些插件。为了更好地掌握它,我鼓励您使用病原体插件。它允许您只git clone
vim插件到~/.vim/bundle/
并保持隔离,而不是混合~/.vim
目录中不同插件的文件。
安装病原体,如here所述。
不要忘记做下一件事(因为它在同一个链接中描述):
将此添加到您的
vimrc
:execute pathogen#infect()
如果您是Vim的全新品牌并缺少
vimrc
,vim ~/.vimrc
并粘贴以下超小型示例:execute pathogen#infect() syntax on filetype plugin indent on
Vim已经拥有cscope支持(参见:help cscope
)。您可以使用:cs f g kfree
之类的命令跳转到符号或文件。虽然不太方便。为了加快速度,您可以使用快捷方式(因此您可以将光标放在某个功能上,按某些组合键并跳转到功能)。要为cscope添加快捷方式,您需要获取cscope_maps.vim
文件。
要使用病原体进行安装,您只需将this repo克隆到~/.vim/bundle
:
$ git clone https://github.com/joe-skb7/cscope-maps.git ~/.vim/bundle/cscope-maps
现在,您应该可以使用快捷方式在vim中的函数和文件之间导航。打开一些内核源文件,将键盘光标放在某个函数调用上,然后按 Ctrl + \ ,然后按 g 。它应该带你到函数实现。或者它可以显示所有可用的功能实现,然后您可以选择使用哪一个:。
对于其余的键映射,请参阅cscope_maps.vim file。
你也可以在vim中使用命令:
:cs f g kmalloc
有关详细信息,请参阅:help cscope
。
ctags仍然可用于导航,例如在查找某些#define
声明时。您可以将光标放在此定义用法上,然后按 g ,然后按 Ctrl + ] 。有关详细信息,请参阅this answer。
下一个技巧可用于在内核中找到结构声明:
:cs f t struct device {
请注意,上面的命令依赖于特定的结构声明样式(在内核中使用),因此我们知道struct声明始终具有以下形式:struct some_stuct {
。这个技巧可能不适用于具有其他编码风格的项目。
如果您正在开发树外模块,则可能需要从内核目录中加载cscope
和ctags
个数据库。它可以通过vim中的下一个命令(在命令模式下)完成。
加载外部cscope数据库:
:cs add /path/to/your/kernel/cscope.out
加载外部ctags数据库:
:set tags=/path/to/your/kernel/tags
还需要对~/.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。
通常使用下一个插件,因此您也可以使用它们:
这些也是有趣的插件,但您可能需要为内核配置它们:
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
使用 Ctrl + Space 进行自动完成。
首先,您要确保终端支持256色。例如,可以使用urxvt-256终端来实现。对于gnome-terminal
,您只需在~/.bashrc
添加下一行:
export TERM="xterm-256color"
完成后,将~/.vimrc
:
set t_Co=256
现在将您喜欢的方案下载到~/.vim/colors
并在~/.vimrc
中选择它们:
set background=dark
colorscheme hybrid
使用哪种配色方案是基于意见的问题。对于初学者,我可能会推荐mrkn256,hybrid和solarized。
有许多好的字体可供编程。 Linux上的许多程序员使用Terminus字体,你可以为初学者尝试。
vim中仍然缺少某些功能。
include/generated/autoconf.h
中的定义,也无法忽略未构建的代码。将所有代码编入索引以在编码时将其用作参考仍然可能有用。gcc -E
),但我不确定它是否为&#39 ; s将为内核工作。)我知道处理这些问题的唯一IDE是Eclipse with CDT。