接下来是Linux内核和常规C项目之间的主要区别(从开发人员的 Angular 来看):
内核是一个非常大的项目(因此您应该选择要索引的代码)
它具有与体系结构相关的代码(并且您一次只对一种特定的体系结构感兴趣;不应为其他体系结构建立索引)
它具有非常具体的coding style,您应遵循(并且应将vim配置为相应地显示代码)
它不使用C标准库,而是具有自己的类似例程(因此,您的索引工具不应为libc header 建立索引)
安装索引工具
要浏览内核代码,我建议使用
cscope
和
ctags
工具。要安装它们,请运行以下命令:
$ sudo aptitude install cscope exuberant-ctags
一点解释:
cscope
:将用于导航代码(在功能等之间切换)。它可以跳转到符号定义,找到所有符号用法,等等。
ctags
:Tagbar
插件(将在后面进行讨论)和Omni completion
(vim中的自动完成机制)所需;也可以用于导航。与Cscope相比,ctags
不是C语言导航的理想选择,因为ctags
仅能跳转到符号定义(而不是其调用者)。
创建索引数据库
现在,您应该索引内核源文件。这里有2种方法:手动创建索引或在内核中使用可用的脚本。如果您不确定哪种方法最适合您,我建议您使用内核脚本,因为它会在幕后进行很多巧妙的操作(例如忽略非生成的源代码并将头文件移到结果列表的顶部)。
但首先,请为您的体系结构/主板配置和构建内核,因为生成的文件可在以后用于改善索引编制过程。
用
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
将它们保留在内核源目录的根目录中。
vim插件
注意:我进一步展示了如何使用病原体来处理Vim插件。但是,既然Vim 8已发布,就可以将
native package loading用于相同的目的。
接下来,我们将为Vim安装一些插件。为了更好地掌握它,我建议您使用
病原菌插件。它允许您仅将
git clone
vim插件添加到
~/.vim/bundle/
并保持隔离,而不是在
~/.vim
目录中混合来自不同插件的文件。
像描述
here一样安装
病原体。
不要忘记做下一件事情(如在同一链接中所述):
Add this to your vimrc
:
execute pathogen#infect()
If you're brand new to Vim and lacking a vimrc
, vim ~/.vimrc
and paste in the following super-minimal example:
execute pathogen#infect()
syntax on
filetype plugin indent on
为Vim安装cscope映射
Vim已经具有cscope支持(请参见
:help cscope
)。您可以使用
:cs f g kfree
之类的命令跳转到符号或文件。不过不是很方便。为了加快操作速度,您可以改用快捷键(这样,您就可以将光标置于某个功能上,按某些组合键并跳至该功能)。为了为cscope添加快捷方式,您需要获取
cscope_maps.vim
文件。
要使用
病原体进行安装,您只需将
this存储库克隆到
~/.vim/bundle
中即可:
$ git clone https://github.com/joe-skb7/cscope-maps.git ~/.vim/bundle/cscope-maps
现在您应该可以使用快捷方式在vim中的功能和文件之间导航。打开一些内核源文件,将键盘光标放在某个函数调用上,然后按Ctrl +\,然后按g。它应该带您到函数实现。或者,它可以显示所有可用的函数实现,然后您可以选择要使用的实现:
。
有关其余的键映射,请参见
cscope_maps.vim文件。
您还可以在vim中使用以下命令:
:cs f g kmalloc
有关详细信息,请参见
:help cscope
。
标签说明
ctags仍可用于导航,例如在查找一些
#define
声明时。您可以将光标放在该定义用法上,然后按g,然后按Ctrl +]。有关详细信息,请参见
this answer。
cscope注意
下一个技巧可用于在内核中找到结构
声明:
:cs f t struct device {
请注意,以上命令依赖于特定的结构声明样式(在内核中使用),因此我们知道结构声明始终具有以下形式:
struct some_stuct {
。此技巧可能不适用于具有另一种编码风格的项目。
树外模块开发说明
如果您正在开发树外模块,则可能需要从内核目录加载
cscope
和
ctags
数据库。可以通过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。
有用的插件
通常使用next插件,因此您也可以找到它们:
NERDTree
Tagbar
file-line
vim-airline
这些也是有趣的插件,但是您可能需要为内核配置它们:
syntastic
YCM
全方位完成
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色
首先,您要确保终端支持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中仍然缺少某些功能。
cscope/ctags不能使用include/generated/autoconf.h
中的定义,并且会忽略未构建的代码。索引所有代码以在编码时用作引用仍然有用。
没有宏扩展(好吧,是那里有一些function(基于gcc -E
),但是我不确定它是否适用于内核。
我知道处理这些问题的唯一IDE是
Eclipse with CDT。
我是一名优秀的程序员,十分优秀!