如何阅读代码还要单独写一篇文章?难道不是随便用一个IDE就可以了吗?回到上一篇文章里介绍的那个问题,需要修改uboot里board_mmc_init函数里的writel(0x66666666,REG_MFP_GPD_L) ,对于初学者如何在uboot代码里找到这句话呢?当时问我这个问题的网友就有这个困惑。因为Uboot和Kernel里有非常多数量的文件,另外为了支持多种芯片,在整个目录里存在大量的同名文件、同名函数。所以如果用一般的IDE把整个工程目录加载进去,然后阅读代码,会相当的不方便,你很难理清楚各个函数之间的调用关系。我曾经尝试过在Windows下用SourceInsight去看内核源码,实在看不下去,而且由于文件太多经常卡住。在网上也看到有人通过一些脚本去精简文件数量再配合SourceInsight的,我也尝试过,感觉也不是很好用。见到过几个高手是直接通过VIM阅读,效率很高,我经过几天的摸索,稍微入了一点门,在这里给初学者做个分享,希望对大家有所帮助。 因为我一开始学的单片机,用Keil软件比较多,咱们就在Ubuntu里构建一个类似于Keil软件常见功能的环境。为了让大家看起来更直观,我找了一个单片机的工程同时放到Ubuntu里和Window下,两边同时对比分析。我们需要在Ubuntu系统里安装配置以下几个工具。Ctags is a programming tool that generates an index (or tag) file of names found in source and header files of various programming languages. Depending on the language, functions, variables, class members, macros and so on may be indexed. These tags allow definitions to be quickly and easily located by a text editor, a code search engine, or other utility.sudo apt-get install ctags安装完成之后,想要使用ctags,必须在你想要查看的代码目录中有tags文件。在执行下述操作前,已经在Ubuntu里~/mcuproject目录下放了一个MCU的工程。先输入vim打开vim窗口,然后在vim命令行窗口输入ts main它的作用是:Search for a particular tag再根据提示输入1 回车就跳转到main函数所在的位置了,有一点需要大家注意的是:一定要在tags所在的目录打开vim,输入ts才能搜到你要找到的tag,在其它目录是不行的,比如我进入到上一级目录,就会提示如下信息了。对比下Windows里Keil环境下,我通常用如下方式去查找:看到这里你是不是有个疑问,为什么Ubuntu下搜索main只有一个地方,但是在Keil下搜索出来了6处。原因是使用ctags搜索的结果是main的定义,而Keil里是只要main这个字符串出现的地方都会被搜索出来。 :ts or :tselect List all of the definitions of the last tag :tn or :tnext Go to the next definition for the last tag :tp or :tprev Go to the previous definition for the last tag :tf or :tfirst Go to the first definition for the last tag :tl or :tlast Go to the last definition for the last tag Ctrl-] Jump to the tag underneath the cursor Ctrl-t Jump back up in the tag stack 通过ctrl+] ,取出当前光标下的word作为tag的名字并进行跳转。你需要查看main函数里的BOARD_InitPins()函数定义,直接在vim里,将光标移动到那里,然后ctrl+]就跳转过去了实现的效果和Keil里点击Go to Definition 效果一致看完了这个函数,想回到原来的地方怎么办呢,ctrl+t即可,对应Keil中下方红框向左的箭头功能。但是只有ctags还不行,因为还有下面3个阅读代码过程中的问题没有解决1)没有类似Keil中下方的工程文件列表,不方便随意选中某个文件浏览2)没有类似Keil中下方的function功能,方便快速找到一个文件中的函数定义3)如果浏览到下面这个文件的BOARD_InitPins函数,我想搜索谁调用它的,就没招了。上述第一个问题,我们通过2.2节的Nerdtree工具实现,第二个问题通过2.3节的Taglist工具实现,第三个问题通过2.4节的cscope工具实现。The NERD tree : A tree explorer plugin for navigating the filesystem The NERD tree allows you to explore your filesystem and to open files and directories. It presents the filesystem to you in the form of a tree which you manipulate with the keyboard and/or mouse. It also allows you to perform simple filesystem operations. 安装方式是先在https://www./scripts/script.php?script_id=1658 网站下载压缩包,将解压缩的文件拷贝到~/.vim/中即可,下面是我~/.vim/中的文件:map <F2> :NERDTreeToggle<CR> nnoremap <F3> :NERDTreeFind<CR> Nerdtree使用方式是在vim打开的文件中,切换到底线命令模式,输入NERDTree,回车就可以了。如果需要关闭Nerdtree,需要切换到底线命令模式,输入NERDTreeClose,这样操作显然很麻烦,这时上面map <F2> :NERDTreeToggle<CR> 这句话就起作用了,我们只需要按F2键就可以来回切换打开与关闭该窗口了。在Nerdtree打开的情况下,有两个窗口,默认打开后光标是在最左侧的窗口,怎么切换到右侧窗口浏览代码呢?通过Ctrl+w+w在两个窗口切换,我们先切换到右边的窗口,然后进入到CLOCK_EnableClock定义的文件里(还记得上一节的Ctrl-]快捷键吧),进入后显示如下这时按一下F3快捷键,注意左侧窗口的变化,自动就定位到该函数所在的文件了,可以很清晰的看到所在文件的目录结构。这就是上面添加的第二句话的作用。另外如果工程里文件很多,你想通过搜索快速找到某个文件,可以使用vim自带的find命令也能完成所需功能。find 会从 path 中搜索文件。所以在使用find之前一定要配置一下path变量(不是PATH环境变量)find gpio_led_output.c或 find g[TAB] Taglist也是vim的一个插件,能将当前vim打开的文件中函数名、变量名等在一个窗口中列出来,并支持通过列出的函数名实现跳转。将Taglist下载下来的压缩包解压缩,将解压缩出来的doc里面的taglist.txt复制到~/.vim/doc/下面,plugin里面的taglist.vim文件拷贝到~/.vim/plugin目录下。这样Taglist这个插件安装完成了。https://www./scripts/script.php?script_id=273 map <F4> :TlistToggle <CR> let Tlist_Use_Right_Window = 1 其中第1句话是建了一个F4的快捷键,用来方便打开和和关闭该插件let Tlist_Show_One_File = 1 "不同时显示多个文件的tag,只显示当前文件的 let Tlist_Exit_OnlyWindow = 1 "如果taglist窗口是最后一个窗口,则退出vim 三部分窗口比例不是很和谐,中间代码窗口太窄,怎么调整窗口大小呢?map <F6> :vertical resize +1<CR> map <F5> :vertical resize -1<CR> :vertical resize 是用来调整当前窗口宽度的。我们在最左侧窗口中先按F5几次,减小当前窗口宽度, 然后到最右侧窗口中也按F5几次,减小当前窗口宽度, 另外你也可以在中间窗口通过Ctrl + - 减小字体来显示的更多内容ctags can be used to take you to the definition of a variable (e.g., a function, variable, or macro). cscope can be used to take you to the call site of a definition (e.g., all function calls, all variable uses, all macro uses).简而言之,它是 ctags 的加强版,ctags 只能让我们跳转到某个 tag 的定义之处,但是无法让我们知道这个 tag 还在哪里出现过,或者被哪个函数调用过,这时候就需要 cscope 来完成该功能了。sudo apt-get install cscope第1步:使用 cscope 生成数据库文件 cscope -Rbkq 其中参数的含义: -R 递归,对子目录也建立数据库 -b 只生成数据库,不进入 scope 界面 -k 生成数据库时,不搜索 /usr/include 目录 -q 生成 cscope.in.out 和 cscope.po.out 文件,加快查找速度 第2步:在vim命令行窗口输入:cs add ./cscope.out通用格式为 :cs find -option labeloption 可以有很多种模式,在 Vim 中使用 :help cscope-find 来查看 option:0 or s: Find this C symbol 1 or g: Find this definition 2 or d: Find functions called by this function 3 or c: Find functions calling this function 4 or t: Find this text string 6 or e: Find this egrep pattern 7 or f: Find this file 8 or i: Find files #including this file cs find g BOARD_InitPins 会直接跳转到这个函数的定义处 cs find c BOARD_InitPins 会直接跳转到调用这个函数的地方 cs find t BOARD_InitPins 会列出以下5个出现该函数的地方 但是这样使用有一个问题:就是我查看一个结果后,如果我还想继续查看其它的结果,还得重新搜索再选择一次。用cscopequickfix,在.vimrc中添加:set cscopequickfix=c-,d-,e-,g-,i-,s-,t-在命令行copen打开quickfix窗口,用cclose关闭,cprev、cnext移动再次cs find t BOARD_InitPins 就会再右下角的窗口里显示,这样查看完一个文件后如果继续查看另外的文件,就可以通过最右下角的窗口切换选择。这种方式打开的窗口是在右下角,看着不是很舒服,怎么弄成Keil那样放到最下方呢,在中间命令行窗口处输入以下内容,就可以在下方显示了先回到我们之前遇到的那个问题,我是如何在Uboot工程里找到需要修改的那个代码地方的,我们先把上一章改动后的0x0666666改回原来的0x66666666。注意上面两步骤没用第二章介绍的方法生成tags和cscope.out文件,原因是因为如果那样操作的话,就把uboot整个文件夹里的所有文件都加进去了,而使用make的方式只生成了实际用到的。F2 、F4 把Nerdtree和Taglist窗口打开,通过F5减小下两侧窗口宽度,Ctrl+-缩小字体:botright copen 打开quickfix窗口我们找到16处,通过简单分析就可以定位到第一个结果就是我们需要的。通过最右侧的Taglist窗口可以看到它是在board_mmc_init这个函数调用的。紧接着我们看下是谁调用的这个函数board_mmc_init::cs find c board_mmc_init我们把光标移动到board_mmc_init 处 Ctrl-t 一下,你会发现进入到不是刚才那个函数定义的地方了,变成了下面这里,这是咋回事??我们再输入:ts board_mmc_init 查看下该函数的定义,发现竟然有三处不过前两个是weak弱定义,所以直接Ctrl-t 跳转的就是上述的第一个结果输入:tn 就会跳转到下一个定义,直到找到正确的定义使用上面的方法就可以一步步的继续分析Uboot代码,这里不是本篇的重点,不详细介绍了。本期相关的资料在https://github.com/TopSemic/NUC972_Linux Lesson19中。本篇为大家介绍了Linux下使用vim配合4个插件实现Linux代码的高效阅读,因为我也是刚学习,所以肯定有很多更好的使用方法还没有掌握,欢迎大家多交流,共同进步,可以在网页下方留言讨论,或者发邮件:Topsemic@sina.com ,微信公众号如下,欢迎关注: 想要获取本文pdf版本的,关注公众号后,回复linux19,即可获取。https://blog.csdn.net/Lius_1006/article/details/79524512 https://blog.csdn.net/cnh294141800/article/details/78208409 https://www./scripts/script.php?script_id=1658 https://guqian110./pages/2015/01/25/learning_vim_ctags_cscope_taglist.html https://blog.csdn.net/dengxiayehu/article/details/6330200 https://yang3wei./blog/2013/01/29/nerdtree-kuai-jie-jian-ji-lu/ https://zhuanlan.zhihu.com/p/85040099 https://blog.csdn.net/jiayu/article/details/2418147 https://blog.csdn.net/menggucaoyuan/article/details/12950711 https://www.cnblogs.com/luosongchao/p/3254451.html https://blog.csdn.net/dengxiayehu/article/details/6330200 https://courses.cs./courses/cse451/10au/tutorials/tutorial_ctags.html https://www./q/6726783 https:///til/navigate-code-with-ctags https://andrew./posts/vim-ctags/ https://courses.cs./courses/cse451/10au/tutorials/tutorial_ctags.html https:///til/navigate-code-with-ctags https:///usevim/nerd-tree-guide-bb22c803dcd2 https:///vim-plugins-nerdtree-vim https://vim./wiki/Resize_splits_more_quickly https://vi./questions/773/how-do-i-change-the-default-size-of-plugin-window-nerdtree-taglist-etc https://blog.csdn.net/qq_16777851/article/details/81782669
|