用于Linux内核开发的Vim配置[关闭]

2024-03-06

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

最重要的是如何在 vim 中导航内核源代码树..我尝试过ctags然而,它的效果却很糟糕。

有人可以给我线索吗?


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

  • 内核是一个非常大的项目(所以你应该选择要索引的代码)
  • 它具有依赖于架构的代码(并且您一次只对一种特定架构感兴趣;不应对其他架构建立索引)
  • 它有非常具体的编码风格 https://www.kernel.org/doc/Documentation/process/coding-style.rst你应该坚持(并且 vim 应该配置为相应地显示代码)
  • 它不使用 C 标准库,而是有自己的类似例程(因此您的索引工具不应索引 libc 标头)

安装索引工具

为了导航内核代码,我建议cscope and ctags工具。要安装它们,请运行以下命令:

$ sudo aptitude install cscope exuberant-ctags

一点解释:

  • cscope:将用于导航代码(在功能之间切换等)。它能够跳转到符号定义、查找所有符号用法等。
  • ctags: 需要用于Tagbar插件(将进一步讨论)和Omni completion(vim 中的自动完成机制);也可用于导航。ctags不像 cscope 那样是 C 代码导航的好选择,因为ctags只能跳转到符号定义(而不能跳转到其调用者)。

创建索引数据库

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

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

索引与scripts/tags.sh

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

Example:

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

where

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

手动索引

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

关于手动索引的见解取自here http://cscope.sourceforge.net/large_projects.html.

首先你需要创建cscope.files文件,其中将列出您要索引的所有文件。例如,我使用 next 命令列出 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

Where dir变量可以具有以下值之一:

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

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

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

$ cscope -b -q -k

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

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

$ ctags -L cscope.files

Ok, cscope and ctags索引数据库已建立,您可以删除cscope.files文件,因为我们不再需要它:

$ rm -f cscope.files

接下来的文件包含索引数据库(例如cscope and ctags):

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

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

vim 插件

NOTE:进一步我展示如何使用pathogen用于处理 Vim 插件。但现在 Vim 8 发布了,人们可以使用原生包加载 https://shapeshed.com/vim-packages/出于同样的目的。

接下来我们要为 vim 安装一些插件。为了更好地掌握它,我鼓励您使用pathogen插入。它让您只需git clonevim 插件到你的~/.vim/bundle/并使它们保持隔离,而不是混合来自不同插件的文件~/.vim目录。

Install pathogen就像它所描述的那样here https://github.com/tpope/vim-pathogen.

不要忘记做接下来的事情(如同一链接中所述):

将其添加到您的vimrc:

execute pathogen#infect()

如果您是 Vim 新手并且缺乏vimrc, vim ~/.vimrc并粘贴以下超简单示例:

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

为 vim 安装 cscope 映射

Vim 已经有 cscope 支持(参见:help cscope)。您可以使用以下命令跳转到符号或文件:cs f g kfree。虽然不是那么方便。要加速操作,您可以使用快捷方式(这样您可以将光标放在某些功能上,按某些组合键并跳转到功能)。为了添加 cscope 的快捷方式,您需要获取cscope_maps.vim file.

要安装它,请使用pathogen你可以克隆this https://github.com/joe-skb7/cscope-maps回购到你的~/.vim/bundle:

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

Now you should be able to navigate between functions and files in vim using shortcuts. Open some kernel source file, put your keyboard cursor on some function call, and press Ctrl+\ followed by g. It should bring you to the function implementation. Or it can show you all available function implementations, then you can choose which one to use: cscope-struct.

对于其余的键映射,请参阅cscope_maps.vim https://github.com/joe-skb7/cscope-maps/blob/master/plugin/cscope_maps.vim#L52 file.

您还可以在 vim 中使用命令,例如:

:cs f g kmalloc

See :help cscope了解详情。

ctags注释

ctags still can be useful for navigation, for example when looking for some #define declaration. You can put cursor on this define usage and press g followed by Ctrl+]. See this answer https://stackoverflow.com/a/1749621/3866447 for details.

cscope注释

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

:cs f t struct device {

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

树外模块开发说明

如果您正在开发树外模块,您可能需要加载cscope and 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 编码风格 https://github.com/vivien/vim-linux-coding-style/commits/master.

有用的插件

接下来的插件很常用,因此您会发现它们也很有用:

  • NERDTree https://github.com/scrooloose/nerdtree
  • Tagbar https://github.com/majutsushi/tagbar
  • 文件行 https://github.com/bogado/file-line
  • vim 航空公司 https://github.com/bling/vim-airline

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

  • 合成的 https://github.com/scrooloose/syntastic
  • YCM https://github.com/Valloric/YouCompleteMe

全方位完成

Vim 7(及更高版本)已经内置了自动完成支持。它调用Omni completion. See :帮助新的全能完成 http://vimdoc.sourceforge.net/htmldoc/version7.html#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

And use Ctrl+Space for auto completion.

养眼的外观

256色

首先您要确保您的终端支持 256 色。例如,可以使用以下方式实现urxvt-256 https://en.wikipedia.org/wiki/Rxvt-unicode终端。为了gnome-terminal您只需将下一行添加到您的~/.bashrc:

export TERM="xterm-256color"

完成后将下一行添加到您的~/.vimrc:

set t_Co=256

配色方案

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

set background=dark
colorscheme hybrid

使用哪种配色方案是强烈基于意见的问题。我可以推荐mrkn256 https://github.com/mrkn/mrkn256.vim, hybrid https://github.com/w0ng/vim-hybrid and 晒过的 https://github.com/altercation/vim-colors-solarized对于初学者。

Font

有很多适合编程的好字体。许多 Linux 程序员都使用Terminus http://terminus-font.sourceforge.net/shots.html字体,初学者可以尝试一下。

已知的缺点

vim 中仍然缺少一些功能。

  1. cscope/ctags 不能使用以下定义include/generated/autoconf.h并忽略未构建的代码。对所有代码进行索引以在编码时将其用作参考仍然可能有用。
  2. 没有宏扩展(嗯,有is some function http://vim.wikia.com/wiki/Macro_expansion_C/C%2B%2B在那里(基于gcc -E),但我不确定它是否适用于内核)。

我所知道的唯一可以处理这些问题的 IDE 是带有 CDT 的 Eclipse https://wiki.eclipse.org/HowTo_use_the_CDT_to_navigate_Linux_kernel_source.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用于Linux内核开发的Vim配置[关闭] 的相关文章

  • Snap-confine 具有提升的权限,并且不受限制,但应该受到限制。拒绝继续避免权限升级攻击

    我已经使用 snap 一段时间了 但最近升级后 当我尝试打开任何应用程序时 出现此错误 Snap confine has elevated permissions and is not confined but should be Refu
  • 在键盘热插拔上加载模块

    我正在尝试学习如何为 Linux 系统编写模块和驱动程序 类似于this https unix stackexchange com questions 120839 usb kernel module does not load on de
  • 跟踪 pthread 调度

    我想做的是创建某种图表 详细说明 Linux 中 两个 线程的执行情况 我不需要查看线程的作用 只需查看它们何时被安排以及持续多长时间 基本上是一条时间线 在过去的几个小时里 我一直在互联网上搜索跟踪 pthread 调度的方法 不幸的是
  • 如何删除树莓派的相机预览

    我在我的 raspberryPi 上安装了 SimpleCv 并安装了用于使用相机板的驱动程序 uv4l 驱动程序 现在我想使用它 当我在 simpleCV shell Camera 0 getImage save foo jpg 上键入时
  • 使用 C++ 输出字符串覆盖 Linux 终端上的最后一个字符串

    假设我有一个命令行程序 有没有办法让我说的时候 std cout lt lt stuff 如果我不做std cout lt lt n 在另一个之间std cout lt lt stuff 东西的另一个输出将覆盖同一行上的最后一个东西 清理行
  • 使用 MongoDB docker 镜像停止虚拟机而不丢失数据

    我已经在 AWS EC2 上的虚拟机中安装了官方的 MongoDB docker 映像 并且数据库上已经有数据 如果我停止虚拟机 以节省过夜费用 我会丢失数据库中包含的所有数据吗 在这些情况下我怎样才能让它持久 有多种选择可以实现此目的 但
  • 测试linux下磁盘空间不足

    我有一个程序 当写入某个文件的磁盘空间不足时 该程序可能会死掉 我不确定是否是这种情况 我想运行它并查看 但我的测试服务器不会很快耗尽空间 有什么办法可以嘲笑这种行为吗 看起来没有任何方法可以在 Ubuntu 中设置文件夹 文件大小限制 并
  • ARM 系统调用的接口是什么?它在 Linux 内核中的何处定义?

    我读过有关 Linux 中的系统调用的内容 并且到处都给出了有关 x86 架构的描述 0x80中断和SYSENTER 但我无法追踪 ARM 架构中系统调用的文件和进程 任何人都可以帮忙吗 我知道的几个相关文件是 arch arm kerne
  • /proc/PID 文件格式

    我想从中检索一些流程信息 proc目录 我的问题如下 中的文件是否有标准格式 proc PID 例如 有这个proc PID status文件与Name t ProcName在第一行 我可以在其他地方用空格代替这个文件吗 t或者类似的东西
  • 退出 bash 脚本但保持进程运行

    我正在运行服务器 需要使用参数执行以下命令 这些脚本目前工作得很好 但问题是当我运行脚本时我无法返回到控制台 它在控制台中保持运行 如果我强行停止它 那么该过程也会停止 我想继续运行该进程并返回到控制台 bin sh php home st
  • Docker DNS 设置

    我尝试使用自定义网络和 dos 设置创建 docker 容器 docker网络创建 driver bridge opt com docker network bridge enable ip masquerade true opt com
  • 在 Ubuntu 上纯粹通过 bash 脚本安装 mysql 5.7

    我想要一个无需任何手动输入即可安装 MySQL 5 7 实例的 bash 脚本 我正在关注数字海洋教程 https www digitalocean com community tutorials how to install mysql
  • 静态链接共享对象?或者损坏的文件?

    我有一个从专有来源获得的库 我正在尝试链接它 但出现以下错误 libxxx so 文件无法识别 文件格式无法识别 Collect2 ld 返回 1 退出状态 确实 ldd libxxx so statically linked 这究竟意味着
  • 什么是标记结构初始化语法?

    struct file operations scull fops owner THIS MODULE llseek scull llseek read scull read write scull write ioctl scull io
  • 大会,你好世界问题

    我正在 Linux 上学习 asm noobuntu 10 04 我得到了以下代码 http asm sourceforge net intro hello html http asm sourceforge net intro hello
  • Linux 文本文件操作

    我有一个格式的文件 a href a href a href a href 我需要选择 之后但 之前的文本 并将其打印在行尾 添加后 例如 a href http www wowhead com search Su a a a a a
  • 在键盘快捷键上插入预定义文本

    我经常插入binding pry当我调试我的 ruby 文件时 当我使用 Vim 时 我希望将其自动化 以避免每次都重新输入 我怎样才能做到呢 我想要映射的确切顺序是 插入新行 Insert binding pry到新创建的行 返回正常模式
  • Linux、ARM:为什么仅当启动时存在 I2C GPIO 扩展器时才创建 gpiochip

    在 imx6sx 硬件平台 NXP 嵌入式 ARM 上使用 Linux 3 14 52 问题是设备树中指定的 PCF8575 I2C GPIO 扩展器不会实例化为 sys class gpio 结构中的设备 除非它们在内核启动期间存在 这些
  • svn:使用vim合并冲突

    我正在尝试看看如何使 svn 中的合并变得容易 This page http svnbook red bean com en 1 7 svn advanced externaldifftools html提到可以使用外部工具进行合并 vim
  • 是否从页面缓存中的脏页面进行文件读取?

    当字节写入文件时 内核不会立即将这些字节写入磁盘 而是将这些字节存储在页缓存中的脏页中 回写缓存 问题是 如果在脏页刷新到磁盘之前发出文件读取 则将从缓存中的脏页提供字节 还是首先将脏页刷新到磁盘 然后进行磁盘读取以提供字节 将它们存储在进

随机推荐