0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何高效的阅读Linux源码

Wildesbeast 来源:今日头条 作者:TopSemic 2020-02-22 14:43 次阅读

1.引言

如何阅读代码还要单独写一篇文章?难道不是随便用一个IDE就可以了吗?回到上一篇文章里介绍的那个问题,需要修改uboot里board_mmc_init函数里的writel(0x66666666,REG_MFP_GPD_L) ,对于初学者如何在uboot代码里找到这句话呢?当时问我这个问题的网友就有这个困惑。

因为Uboot和Kernel里有非常多数量的文件,另外为了支持多种芯片,在整个目录里存在大量的同名文件、同名函数。所以如果用一般的IDE把整个工程目录加载进去,然后阅读代码,会相当的不方便,你很难理清楚各个函数之间的调用关系。我曾经尝试过在Windows下用SourceInsight去看内核源码,实在看不下去,而且由于文件太多经常卡住。在网上也看到有人通过一些脚本去精简文件数量再配合SourceInsight的,我也尝试过,感觉也不是很好用。见到过几个高手是直接通过VIM阅读,效率很高,我经过几天的摸索,稍微入了一点门,在这里给初学者做个分享,希望对大家有所帮助。

2.工具安装与使用

因为我一开始学的单片机,用Keil软件比较多,咱们就在Ubuntu里构建一个类似于Keil软件常见功能的环境。为了让大家看起来更直观,我找了一个单片机的工程同时放到Ubuntu里和Window下,两边同时对比分析。我们需要在Ubuntu系统里安装配置以下几个工具。

2.1 ctags

2.1.1 ctags安装配置

以下一段话摘自于维基百科: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 --version

使用ctags --list-languages可以查看ctags支持的编程语言

使用ctags --list-maps可以查看ctags支持的编程语言对应的文件扩展名

使用ctags --list-kinds可以查看ctags识别的语法元素,使用ctags --list-kinds=c可单查看C语言识别的语法元素

安装完成之后,想要使用ctags,必须在你想要查看的代码目录中有tags文件。2.1.2 ctags使用在执行下述操作前,已经在Ubuntu里~/mcuproject目录下放了一个MCU的工程。第1步: ctags -R *生成tags文件。

第2步:需要找到main函数定义在哪里,先输入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命令,还有其他相关命令:

: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

第3步:ctags两个常用的快捷键

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工具实现。

2.2安装配置Nerdtree

2.2.1 Nerdtree安装

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.vim.org/scripts/script.php?script_id=1658 网站下载压缩包,将解压缩的文件拷贝到~/.vim/中即可,下面是我~/.vim/中的文件:

如果没有.vim 目录的话,自己创建下即可。

2.2.2 Nerdtree使用

在使用前,现在~/.vimrc中添加以下两句话:

map :NERDTreeToggle

nnoremap :NERDTreeFind

具体什么用途,下文马上解释。Nerdtree使用方式是在vim打开的文件中,切换到底线命令模式,输入NERDTree,回车就可以了。

显示效果如下,多出来左侧部分就是Nerdtree

如果需要关闭Nerdtree,需要切换到底线命令模式,输入NERDTreeClose,这样操作显然很麻烦,这时上面map :NERDTreeToggle 这句话就起作用了,我们只需要按F2键就可以来回切换打开与关闭该窗口了。在Nerdtree打开的情况下,有两个窗口,默认打开后光标是在最左侧的窗口,怎么切换到右侧窗口浏览代码呢?通过Ctrl+w+w在两个窗口切换,我们先切换到右边的窗口,然后进入到CLOCK_EnableClock定义的文件里(还记得上一节的Ctrl-]快捷键吧),进入后显示如下

这时按一下F3快捷键,注意左侧窗口的变化,自动就定位到该函数所在的文件了,可以很清晰的看到所在文件的目录结构。这就是上面添加的第二句话的作用。

另外如果工程里文件很多,你想通过搜索快速找到某个文件,可以使用vim自带的find命令也能完成所需功能。find 会从 path 中搜索文件。所以在使用find之前一定要配置一下path变量(不是PATH环境变量)具体方法是:在右侧窗口中,进入命令行窗口:set path=./**然后

find gpio_led_output.c或

find g[TAB]

即可搜索文件

2.3 安装配置Taglist

2.3.1 Taglist安装

Taglist也是vim的一个插件,能将当前vim打开的文件中函数名、变量名等在一个窗口中列出来,并支持通过列出的函数名实现跳转。将Taglist下载下来的压缩包解压缩,将解压缩出来的doc里面的taglist.txt复制到~/.vim/doc/下面,plugin里面的taglist.vim文件拷贝到~/.vim/plugin目录下。这样Taglist这个插件安装完成了。下载地址在:https://www.vim.org/scripts/script.php?script_id=2732.3.2 Taglist使用在使用前,现在~/.vimrc中添加以下两句话:

map :TlistToggle

let Tlist_Use_Right_Window = 1

其中第1句话是建了一个F4的快捷键,用来方便打开和和关闭该插件第2句话是将该插件窗口放到最后侧。另外根据需要你还可以选择是否添加以下特性:

let Tlist_Show_One_File = 1 "不同时显示多个文件的tag,只显示当前文件的
let Tlist_Exit_OnlyWindow = 1 "如果taglist窗口是最后一个窗口,则退出vim

按下F4打开Taglis后,整体窗口显示如下:

三部分窗口比例不是很和谐,中间代码窗口太窄,怎么调整窗口大小呢?在~/.vimrc中添加以下两句话:

map :vertical resize +1

map :vertical resize -1

:vertical resize 是用来调整当前窗口宽度的。

我们在最左侧窗口中先按F5几次,减小当前窗口宽度,

然后到最右侧窗口中也按F5几次,减小当前窗口宽度,

就变成这样了:

另外你也可以在中间窗口通过Ctrl + - 减小字体来显示的更多内容

Ctrl + + 为增大字体

2.4 cscope

2.4.1 cscope安装配置

先看下ctags和cscope的区别: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验证是否安装成功的方式可以输入cscope --version

表示安装成功

2.4.2 cscope使用

第1步:使用 cscope 生成数据库文件

cscope -Rbkq

其中参数的含义:

-R 递归,对子目录也建立数据库

-b 只生成数据库,不进入 scope 界面

-k 生成数据库时,不搜索 /usr/include 目录

-q 生成 cscope.in.out 和 cscope.po.out 文件,加快查找速度

第2步:在vim命令行窗口输入:cs add ./cscope.out第3步:通用格式为 :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个出现该函数的地方

通过选择不同的数字,可以查看具体不同出现的位置。这个搜索结果和Keil里搜索的结果一样:

但是这样使用有一个问题:就是我查看一个结果后,如果我还想继续查看其它的结果,还得重新搜索再选择一次。该问题的解决方法是:用cscopequickfix,在.vimrc中添加:set cscopequickfix=c-,d-,e-,g-,i-,s-,t-

在命令行copen打开quickfix窗口,用cclose关闭,cprev、cnext移动再次cs find t BOARD_InitPins 就会再右下角的窗口里显示,这样查看完一个文件后如果继续查看另外的文件,就可以通过最右下角的窗口切换选择。

这种方式打开的窗口是在右下角,看着不是很舒服,怎么弄成Keil那样放到最下方呢,在中间命令行窗口处输入以下内容,就可以在下方显示了:botright copen

3.Uboot实战应用

先回到我们之前遇到的那个问题,我是如何在Uboot工程里找到需要修改的那个代码地方的,我们先把上一章改动后的0x0666666改回原来的0x66666666。第1步:进入到Uboot所在目录make cscope

第2步:make ctags

注意上面两步骤没用第二章介绍的方法生成tags和cscope.out文件,原因是因为如果那样操作的话,就把uboot整个文件夹里的所有文件都加进去了,而使用make的方式只生成了实际用到的。第3步:vim:cs add ./cscope.out第4步:F2 、F4 把Nerdtree和Taglist窗口打开,通过F5减小下两侧窗口宽度,Ctrl+-缩小字体:botright copen 打开quickfix窗口第5步::cs find t 0x66666666我们找到16处,通过简单分析就可以定位到第一个结果就是我们需要的。

你如果是在整个目录去查询,就远远不止这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 就会跳转到下一个定义,直到找到正确的定义

另外输入ts 就可以看到最后一次tag结果。

使用上面的方法就可以一步步的继续分析Uboot代码,这里不是本篇的重点,不详细介绍了。

4.结束语

本篇为大家介绍了Linux下使用vim配合4个插件实现Linux代码的高效阅读,因为我也是刚学习,所以肯定有很多更好的使用方法还没有掌握,欢迎大家多交流,共同进步,可以在网页下方留言讨论

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11297

    浏览量

    209370
  • IDE
    IDE
    +关注

    关注

    0

    文章

    338

    浏览量

    46745
  • Uboot
    +关注

    关注

    4

    文章

    125

    浏览量

    28219
收藏 人收藏

    评论

    相关推荐

    Linux内核开发工具介绍

    进行嵌入式Linux产品开发,往往需要对内核进行裁剪和定制,以满足嵌入式产品的功能和性能需求。本文介绍几种阅读Linux内核源码的工具和方法。
    发表于 12-29 15:20 4708次阅读
    <b class='flag-5'>Linux</b>内核开发工具介绍

    一文详解Linux内核源码组织结构

    概要:本文内容包含Linux源码树结构分析、Linux Makefile分析、Kconfig文件分析、Linux内核配置选项分析。这些知识是为了理解内核文件的组织形式,为具体移植内核做
    的头像 发表于 05-10 19:28 5758次阅读

    Linux内核源码之我见——内核源码的分析方法

    一、内核源码之我见Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次。如果想透析Linux,深入操作系统的本质,
    发表于 05-11 07:00

    下载编译源码的要点和搭建源码阅读环境的方法

    下载编译源码的要点和搭建源码阅读环境的方法。下载编译源码,一方面是为了搭建源码阅读环境,另一方面
    发表于 01-10 06:49

    Linux内核源代码(free)

    一些基本概念 操作系统的基本概念 I386系统的基本概念 Linux简介 源码阅读和project环境 Linux 2.6.26 源码
    发表于 01-08 17:41 26次下载

    几个RT-Linux 源码

    几个RT-Linux 源码
    发表于 01-08 14:27 11次下载

    Linux内核阅读心得体会

    Linux内核阅读心得体会
    发表于 10-24 08:55 8次下载
    <b class='flag-5'>Linux</b>内核<b class='flag-5'>阅读</b>心得体会

    需要掌握的Linux内核源码分析方法

    Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次。如果想透析Linux,深入操作系统的本质,阅读内核
    发表于 04-28 16:54 814次阅读
    需要掌握的<b class='flag-5'>Linux</b>内核<b class='flag-5'>源码</b>分析方法

    分享一个超级实用的源码阅读小技巧

    工欲善其事必先利其器; 我发现函数调用图可以让我们更加直观地了解到源码函数直接的调用和层次关系,提高阅读源码的效率 。 1 前言 看源码的时候,心血来潮想弄一下函数之前的调用关系,想起
    的头像 发表于 05-29 11:50 2056次阅读
    分享一个超级实用的<b class='flag-5'>源码</b><b class='flag-5'>阅读</b>小技巧

    如何选择合适的工具来阅读源代码

    在做嵌入式 Linux 软件开发的时候,经常会阅读大型工程源码,比如 uboot 源代码,Linux Kernel 源码等。
    的头像 发表于 03-30 14:01 1164次阅读

    ROC RK3566 PC Linux SDK源码

    电子发烧友网站提供《ROC RK3566 PC Linux SDK源码包.txt》资料免费下载
    发表于 09-21 15:03 20次下载
    ROC RK3566 PC <b class='flag-5'>Linux</b> SDK<b class='flag-5'>源码</b>包

    AIO 3568J Linux SDK源码

    电子发烧友网站提供《AIO 3568J Linux SDK源码包.txt》资料免费下载
    发表于 09-21 11:02 10次下载
    AIO 3568J <b class='flag-5'>Linux</b> SDK<b class='flag-5'>源码</b>包

    阅读开源项目源码的实用技巧(下)

    这句话其实是高效 debug 的关键。初看源码时「猜」是很重要且很有效的手段,结合 IDE 的搜索功能,能够帮我们快速定位关键代码。
    的头像 发表于 04-12 11:37 749次阅读
    <b class='flag-5'>阅读</b>开源项目<b class='flag-5'>源码</b>的实用技巧(下)

    如何去阅读源码,我总结了18条心法

    在一个优秀的开源项目中,设计模式处处存在,所以在你开始阅读源码之前最好先了解一下常见的一些设计模式。当你了解了一些设计模式以后,在源码中遇到了相关的设计模式,你就可以快速明白代码结构的设计,从而以整体的视角去
    的头像 发表于 07-17 16:00 809次阅读
    如何去<b class='flag-5'>阅读</b><b class='flag-5'>源码</b>,我总结了18条心法

    获取Linux内核源码的方法

    关键功能,今天小编就给各位小伙伴介绍一下如何获取Linux内核源码。获取Linux内核源码的渠道Linux有一个庞大的开源社区,每个人都可以
    的头像 发表于 12-13 09:49 649次阅读
    获取<b class='flag-5'>Linux</b>内核<b class='flag-5'>源码</b>的方法