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

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

3天内不再提示

浅论Linux 内核函数调用关系的验证方法

电子工程师 来源:微型机与应用第21期 刘志 作者:微型机与应用第 2021-04-02 11:30 次阅读

摘 要: 作为最流行的开源操作系统Linux在各行各业得到了广泛的应用。因此了解Linux 内核的架构及工作机制就显得非常重要。然而目前对Linux 内核的主要学习途径是各种教科书以及经验博客,而对于Linux内核的实时动态监控技术却很少有人了解。本文提供一种动态监视内核运行过程的方法。通过此方法可以动态地观察Linux内核的函数调用情况,以及CPU寄存器值等动态信息

0 引言

众所周知Linux是目前公认的最好的开源操作系统。它被广泛应用于各行各业。因此对Linux内核的学习就显得尤为重要。目前对于Linux内核的学习一般都是通过以下几个途径。

⑴通过经典教材,这些教材一般由著名的Linux 内核开发者编写。比较常用的如参考文献[1-3] 。通过这些教材读者可以从宏观的角度去了解Linux内核的整体架构以及运行机制。但是由于教科书只能提供基于作者理解的内核架构,读者无法从中获得直观的内核的动态运行状况,而这点对加深内核的理解是非常有益的。

⑵通过Linux内核的邮件列表,Linux 的开发者可以从这些列表中与其他开发者交流遇到的问题。

⑶Linux内核的源代码。Linux 的源代码涵盖了Linux的所有实现细节,但由于源代码的数量非常巨大,所以开发者往往需要在了解了相关机制以后才可以定位代码片段的位置。

以上提到的是目前了解和学习Linux内核的一些主要途径,通过这些途径可以了解内核的大体运行机制。然而这些方法都存在一个相同的问题就是无法动态实时地反应内核的运行情况。而在分析Linux内核的运行机制尤其是在遇到通过函数指针的赋值调用的情况时能够动态实时地检测内核的运行情况是非常必要的。

本文将介绍一种基于 DDD (Data Display Debugger)[4]、 BusyBox [5]、QEMU(Quick Emulator)[6]工具来对Linux内核代码运行进行动态检测的方法。

1 相关实验工具简介

本文将利用QEMU[7]搭建一个虚拟机,同时用BusyBox[5]在虚拟机上搭建一个小型Linux文件系统,然后用命令行调试程序DDD[4]来监视Linux内核的运行情况。

1.1 QEMU简介

QEMU[7]是一套由Fabrice Bellard所编写的模拟处理器的自由软件。QEMU能模拟至接近真实电脑的速度。通过QEMU可以建立一个运行目标内核的轻量级的虚拟机,并可以像调试普通应用程序一样对虚拟机中的内核代码进行单步调试,从而可以很清楚地看到代码跳转过程、CPU寄存器的变化、内核堆栈的变化等内核动态运行信息。

1.2 DDD简介

DDD(Data Display Debugger)是命令行调试程序,它特有的图形数据显示功能可以把数据结构按照图形的方式显示出来。DDD的功能非常强大,可以调试用C\C++Ada、Fortran、Pascal、Modula-2和Modula-3编写的程序。可以超文本方式浏览源代码;同时可以进行断点设置、显示各种数据结构之间的关系并由此将数据结构以图形化形式显示。

1.3 BusyBox简介

BusyBox集成压缩了 Linux 的许多工具和命令,也包含了 Android 系统的自带的shell。BusyBox将许多具有共性的小版本的Unix工具结合到一个单一的可执行文件。BusyBox提供了一个比较完善的环境,可以运行任何小的系统或嵌入式系统

2 验证流程

2.1 实验环境

本文将在Linux发行版Ubuntu 12.04上搭建实验工具。

2.2 实验工具搭建说明

这个工具套件的环境搭建由以下几个步骤组成:

⑴编译内核

选用Linux Kernel 3.5.4的内核版本。在进行内核代码的验证之前先要对目标内核进行编译,用wget命令从内核服务器下载3.5.4版本的内核,在对其编译之后就能获得内核镜像文件bzImage。

⑵安装QEMU

从QEUM的官方网站[5]上下载QEMU的最新源码文件。而后切换到 QEMU 的源码目录输入./configure生成 makefile 文件。在完成后输入编译命令make 开始编译QEMU。最后用make install命令将QEMU安装到系统中。

⑶制作根文件系统

利用DD 命令建立一个大小为10 MB的磁盘镜像文件。本实验内核将运行在这个系统上。在完成后挂载刚刚生成的镜像。在镜像中建立Linux根目录下的文件夹dev、proc、sys。

⑷安装 BusyBox 到根文件系统

在BusyBox的官方网站[8]上下载最新的BusyBox 源码。切换到BusyBox的源码目录,输入命令 make menuconfig 配置编译选项。

在弹出的配置菜单中勾选静态编译的选项(BusyBox Settings→Build options→Build BusyBox as a static binary)。

完成后输入命令make 开始编译。最后用命令make install 把编译好的BusyBox文件系统安装到刚刚生成的镜像根文件系统中。

通过以上4个步骤就可以完成Linux内核运行验证系统的搭建。

3 验证演示实例

3.1 验证的内核模块

在本文中将演示验证Linux 内核中虚拟终端(TTY)子系统open操作的运行流程。通过阅读源代码,总结出TTY子系统open操作的主要流程如图1所示。

6357782753806600002796520.jpg

3.2 DDD中显示的内核运行结果

⑴因为在Linux内核中TTY设备被归于字符型设备,所以TTY初始化的第一步是将申请的设备描述结构体的open操作函数指针(def_chrfops->chrdec_open)赋值成字符设备open函数(chrdev_open)的函数指针。 程序代码如下:

const struct file_operations def_chr_fops = {

.open = chardev_open,

.llseek = nop_llseek,

};

⑵调用字符设备子系统的open函数进入char_open函数。相关代码如下:

static int chardev_open(struct *inode,struct file *filp){

struct dev *p;

struct cdev *new =NULL;

int ret = 0;

}

⑶检测内核kobject链表是否有TTY设备,如果找不到这个设备,则返回错误。其内核代码如下所示:

if(!kobj)

return -ENXIO;

new = container_of(kobj, struct codec,kobj);

spin_lock(&cdev_lock);

p = inode->i_cdev;

⑷运行内核 filip结构体的open函数。以下为相关代码:

if(filp->f_op->open){

ret = filp->f_op->open(inode,filp);

if(ret)

goto out_cdev_put;

}

通过DDD对Linux内核运行的检测结果发现,Linux内核中TTY子系统的打开操作的流程与我们通过源代码分析出来的结论是一致的。从而验证了我们流程图的正确性。

4 结束语

本文介绍了一个基于DDD、QEMU、BusyBox工具套件,对Linux内核进行动态检测的方法。通过该方法能够对这个Linux内核的实时运行情况进行监测,从而使内核学习者和研究者对Linux 的整个运行机制有了立体的了解,对内核的运行有直观深刻的印象。本文还以虚拟终端(TTY)子系统open操作为例进行了完整的分析。展示了这个方法对一个具体的应用场景进行动态分析的过程及通过这个套件捕捉到Linux内核函数指针的动态赋值及调用过程。

参考文献

[1] Bovet D P, Cesati M. Understanding the Linux Kernel [M]. O'Reilly,2006.

[2] Wolfgang Mauerer.Professional Linux Kernel Architecture [M]. Wiley India Pvt. Limited, 2008.

[3] Robert Love. Linux Kernel Development [M]. Addison-Wesley Professional, 2010.

[4] Zeller A, Lütkehaus D. DDD-a free graphical front-end for UNIX debuggers [J]. ACM Sigplan Notices [C]. 1996, 31(1): 22-27.

[5] Bellard, Fabrice. QEMU open source processor emulator [OL]. (2007-04-03)[2014-07-15] (2007).

[6] Wells N. BUSYBOX: A swiss army knife for Linux [J]. Linux Journal, 2000, 2000(78es): 10.

[7] Fabrice B. QEMU, a fast and portable dynamic translator[C]. USENIX Annual Technical Conference, FREENIX Track, 2005.

[8] Andersen, Erik. BusyBox[OL]. (2008-01-19)[2014-07-15] BusyBox.net (2008).

编辑:jq

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

    关注

    1

    文章

    316

    浏览量

    21614
  • ddd
    ddd
    +关注

    关注

    0

    文章

    23

    浏览量

    2918
  • 函数调用
    +关注

    关注

    0

    文章

    19

    浏览量

    2584
  • qemu
    +关注

    关注

    0

    文章

    57

    浏览量

    5330
收藏 人收藏

    评论

    相关推荐

    压敏电阻压力与电阻函数关系

    压敏电阻(也称为力敏电阻)是一种将机械力转换为电信号的元件,其电阻值随外部压力的变化而变化。这种变化关系通常可以通过实验测定,并可以近似地用数学函数来表示。然而,需要注意的是,具体的函数关系
    的头像 发表于 09-25 09:30 472次阅读

    linux驱动程序如何加载进内核

    Linux系统中,驱动程序是内核与硬件设备之间的桥梁。它们允许内核与硬件设备进行通信,从而实现对硬件设备的控制和管理。 驱动程序的编写 驱动程序的编写是Linux驱动开发的基础。在编
    的头像 发表于 08-30 15:02 369次阅读

    linux驱动程序的编译方法是什么

    Linux驱动程序的编译方法主要包括两种: 与内核一起编译 和 编译成独立的内核模块 。以下是对这两种方法的介绍: 一、与
    的头像 发表于 08-30 14:46 402次阅读

    Linux内核测试技术

    Linux 内核Linux操作系统的核心部分,负责管理硬件资源和提供系统调用接口。随着 Linux
    的头像 发表于 08-13 13:42 428次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>测试技术

    函数多层调用的主要注意事项分析

    应用方案设计中,开发者经常会碰到某个子函数需要多次多级调用的情况。
    的头像 发表于 03-27 15:36 729次阅读
    子<b class='flag-5'>函数</b>多层<b class='flag-5'>调用</b>的主要注意事项分析

    回调函数(callback)是什么?回调函数的实现方法

    回调函数是一种特殊的函数,它作为参数传递给另一个函数,并在被调用函数执行完毕后被调用。回调
    发表于 03-12 11:46 2700次阅读

    linux用gdb调试遇到函数调用怎么办?

    linux用gdb调试遇到函数调用怎么办? 在Linux上使用GDB调试时,遇到函数调用是一个常
    的头像 发表于 01-31 10:33 677次阅读

    Linux内核中信号相关的系统调用

    ,sys_sigaction()和sys_rt_sigaction()几乎相同,因此C库中包含的sigaction()包装函数最终会调用sys_rt_sigaction()而不是sys_sigaction()。
    的头像 发表于 01-20 09:34 645次阅读

    Linux内核中信号的传递过程

    前面我们已经介绍了内核注意到信号的到来,调用相关函数更新进程描述符以便进程接收处理信号。但是,如果目标进程此时没有运行,内核则推迟传递信号。现在,我们看看
    的头像 发表于 01-17 09:51 1058次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>中信号的传递过程

    Linux内核中信号详解

      1 信号的角色 1.1 x86/64架构信号定义 1.2 ARM架构信号定义 1.3 RISC-V架构信号定义 1.4 信号的系统调用 1.5 信号工作原理 2 信号的响应行为 3 POSIX
    的头像 发表于 01-13 09:40 1328次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>中信号详解

    linux内核系统调用之参数传递

    与普通函数一样,系统调用通常需要一些输入/输出参数,这些参数可能包括实际值(即数字)、用户模式进程地址空间中的变量地址,甚至包括指向用户模式函数指针的数据结构的地址(参见第11章“信号相关的系统
    的头像 发表于 12-20 09:32 1418次阅读

    Linux系统中调用脚本的常见方法

    linux系统中有多种方法可以在系统启动后调用脚本,接下来介绍几种常见的方法
    的头像 发表于 12-13 18:16 991次阅读

    获取Linux内核源码的方法

    (ELF1/ELF1S开发板及显示屏)Linux内核是操作系统中最核心的部分,它负责管理计算机硬件资源,并提供对应用程序和其他系统组件的访问接口,控制着计算机的内存、处理器、设备驱动程序和文件系统等
    的头像 发表于 12-13 09:49 615次阅读
    获取<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>源码的<b class='flag-5'>方法</b>

    Linux内核自解压过程分析

    uboot完成系统引导以后,执行环境变量bootm中的命令;即,将Linux内核调入内存中并调用do_bootm函数启动内核,跳转至kern
    的头像 发表于 12-08 14:00 845次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>自解压过程分析

    python调用math函数方法

    中。本文将详细介绍math模块中的各种数学函数调用方法,包括函数的功能、参数的使用和返回值的含义等方面,以帮助读者更好地理解和应用这些函数
    的头像 发表于 11-22 11:01 2779次阅读