• Linux kernel分析前的准备


    分析工具

    “欲善其事,先利其器”。Linux内核的代码量非常大,如果没有一个好的察看分析工具,那将是一件非常繁琐的事情。

    Vim+cscope

    cscope,如果你知道ctags,那么它是一个比ctags更强大的工具,如果你不知道ctags,也没关系,cscope使你可以在一大堆的代码中进行轻松查找函数、宏、结构体等标示符定义处、使用点,并进行跳转。

    安装

    cscope在Fedora和Ubuntu的源里都有,可以直接yum或apt-get。

    Fedora下cscope安装好后就直接可以与Vim一起使用,但Ubuntu下安装好cscope后,还要在/ect/vim/vimrc文件的最后添加如下内容:

    if has("cscope")
            set csprg=/usr/bin/cscope
            set csto=0
            set cst
            set nocsverb
            " add any database in current directory
            if filereadable("cscope.out")
                cs add cscope.out
            " else add database pointed to by environment
            elseif $CSCOPE_DB != ""
                cs add $CSCOPE_DB
            endif
            set csverb
    endif

    这使Vim可以自动加载cscope生成的索引文件。要获取更多信息,在Vim中输入“:help cscope"也可以得到。

    使用

    首先在源码目录下用cscope生成cscope索引文件,

    cscope -bqR

    当前目录下会生成cscope.out,cscope.in.out和cscope.po.out三个索引文件。

    其中参数含义如下:

    -b 只生成索引文件,并不进入cscope交互界面;

    -q 生成cscope.in.out和cscope.po.out两个文件,加快查找;

    -R 遍历子目录。

    我只用到这三个命令,如果想了解更多,可以察看help或man文档。

    现在就可以用了,如果你不想给自己找一些不必要的麻烦,你应该在有cscope.out,cscope.in.out和cscope.po.out的目录直接运行Vim:

    vim .(或者vim ./)

    在这里再介绍一个Vim插件NERD tree,此插件可以使vim中的目录更好看,效果图如下:

    在Vim中,cscope使用最多的命令是find,可以简写为f。想要获取Vim中cscope的其他命令,可以输入:

    :cs help

    来获取,结果如下:

    cscope 命令:

    add  :添加一个新的数据库             (用法: add file|dir [pre-path] [flags])
    find :查询一个模式                   (用法: find c|d|e|f|g|i|s|t name)
           c: Find functions calling this function
           d: Find functions called by this function
           e: Find this egrep pattern
           f: Find this file
           g: Find this definition
           i: Find files #including this file
           s: Find this C symbol
           t: Find this text string
    help :显示此信息                     (用法: help)
    kill :结束一个连接                   (用法: kill #)
    reset:重置所有连接                   (用法: reset)
    show :显示连接                       (用法: show)

    我经常使用的有:

    c 查找一个函数被那个函数调用,此命令仅限于函数对函数。我一般会用s来代替c,因为可能结构体中也有使用了该函数,那么c命令是查不到的,而s就可以。

    f 查找一个文件。

    g 查找某个函数的定义处。

    s 查找一个标示符,结果会包括c、g命令的结果和其他地方使用了此标示符的地方(标示符不同于字符串,它是独立存在的,并不是一个字符串的一部分)。

    t 此命令是最耗时的命令,它在代码中查找所有含有此字符串的地方。

    最后当你找到你要找的项,输入数字标号就会跳转到你要着的那一项。

    实例

    代码:Linux内核代码,版本3.5.4

    具体函数为fs/btrfs/acl.c文件中的第一个函数btrfs_get_acl。

    查找此函数的定义处

    在Vim中输入:

    :cs f g btrfs_get_acl

    查找此函数的定义处,显示如下:

    Cscope tag: btrfs_get_acl
       #   行    文件名 / 上下文 / 行
       1     31  fs/btrfs/acl.c <<btrfs_get_acl>>
                 struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
       2   3100  fs/btrfs/ctree.h <<btrfs_get_acl>>
                 #define btrfs_get_acl NULL

    我们发现有两处,但仔细看看,第二项并不是你要找的,第一项才是你要找的。

    查找此函数被那些函数调用

    :cs f c btrfs_get_acl

    显示如下:

    Cscope tag: btrfs_get_acl
       #   行    文件名 / 上下文 / 行
       1     88  fs/btrfs/acl.c <<btrfs_xattr_acl_get>>
                 acl = btrfs_get_acl(dentry->d_inode, type);
       2    207  fs/btrfs/acl.c <<btrfs_init_acl>>
                 acl = btrfs_get_acl(dir, ACL_TYPE_DEFAULT);
       3    253  fs/btrfs/acl.c <<btrfs_acl_chmod>>
                 acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);

    其中上面的内容简单介绍一下,1、2、3是标号;后面跟着的数字是在文件中的行号;后面是文件名;双尖括号里的是调用btrfs_get_acl函数的函数;下面的一行是调用此函数的内容,有时,你可以从文件名和内容猜测是不是你要着的东西。

    查找此标示符在那些地方出现

    :cs f s btrfs_get_acl
    显示如下:
    Cscope tag: btrfs_get_acl
       #   行    文件名 / 上下文 / 行
       1   3095  fs/btrfs/ctree.h <<GLOBAL>>
                 struct posix_acl *btrfs_get_acl(struct inode *inode, int type);
       2   3100  fs/btrfs/ctree.h <<GLOBAL>>
                 #define btrfs_get_acl NULL
       3   7624  fs/btrfs/inode.c <<GLOBAL>>
                 .get_acl = btrfs_get_acl,
       4   7629  fs/btrfs/inode.c <<GLOBAL>>
                 .get_acl = btrfs_get_acl,
       5   7697  fs/btrfs/inode.c <<GLOBAL>>
                 .get_acl = btrfs_get_acl,
       6   7708  fs/btrfs/inode.c <<GLOBAL>>
                 .get_acl = btrfs_get_acl,
       7   7722  fs/btrfs/inode.c <<GLOBAL>>
                 .get_acl = btrfs_get_acl,
       8     31  fs/btrfs/acl.c <<btrfs_get_acl>>
                 struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
       9     88  fs/btrfs/acl.c <<btrfs_xattr_acl_get>>
                 acl = btrfs_get_acl(dentry->d_inode, type);
      10    207  fs/btrfs/acl.c <<btrfs_init_acl>>
                 acl = btrfs_get_acl(dir, ACL_TYPE_DEFAULT);
      11    253  fs/btrfs/acl.c <<btrfs_acl_chmod>>
                 acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);

    从上面的查找内容可以看出,除了刚刚上面两种查找到的结果,其中还有一些其他的项。

    其中第一项是此函数的声明;第二项和第八项是查找定义处时就有的;第三项到第七项是其他地方调用到地方,这些地方是结构体对它调用。

    想更好的使用,还需要你去慢慢练习

    分析方法

    方法有多种,看你怎么用!

    如果能找到资料,那我们从资料入手,这是最好的办法;

    如果我们只能找到一些零散的资料,这些资料中并没有对代码的分析,只是对这个软件进行了一些功能介绍,我们可以从这些功能入手,从这些功能的每一个点入手,找关键字,然后将这些功能定位到代码中,接下来再从代码开始分析;

    但有时没有任何的资料,那就要从代码中来,你可以先从代码的入口开始,一般是main函数,但Linux内核代码太大,如果这样分析的话,我们面对的是整个内核代码,这将是一个浩大的工程,你会望而却步的,所以,你要从点入手,内核代码非常规程,模块化特别好,你可以从单个模块入手,然后在这个模块中寻找更小的功能点开始。

    资料搜索

    首选google,其次百度。搜索是可以将想要搜索的信息精简,放小范围。

    搜索多个结果进行对比。

    做笔记,我喜欢用MediaWiki作为我的文档管理器,MediaWiki可以很好的对你的文档各个版本进行记录。你可以回到N天前你修改的文档。

    经验积累

    Linux内核中用到了许多经典的编程思想,我们会经常见到不懂的点,这些点我们可以从网上基本上都能找到,但是,有些点,我们看一遍之后几天又忘了,这时做笔记就尤为重要。

    以上都是我的经验之谈,更多还需要自己实践。

  • 相关阅读:
    Tensorflow2.0笔记07——神经网络复杂度
    Tensorflow2.0笔记06——扩展方法(本地读取数据集、简易神经网络、优化)
    Tensorflow2.0笔记05——程序实现鸢尾花数据集分类
    Tensorflow2.0笔记04——Tensorflow常用函数
    Tensorflow2.0笔记03——基本概念
    Tensorflow2.0笔记02——神经网络的设计过程
    菜鸟弹性调度系统的架构设计——阅读心得
    微博深度学习平台架构和实践——阅读心得
    豆瓣基础架构——阅读心得
    美团云的网络架构演进之路——阅读心得
  • 原文地址:https://www.cnblogs.com/snowsolf/p/Linux-kernel-analyse.html
Copyright © 2020-2023  润新知