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

    文章

    321

    浏览量

    23324
  • ddd
    ddd
    +关注

    关注

    0

    文章

    23

    浏览量

    3116
  • 函数调用
    +关注

    关注

    0

    文章

    21

    浏览量

    2765
  • qemu
    +关注

    关注

    0

    文章

    57

    浏览量

    6011
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    openKylin受邀参加Linux内核领域顶级技术峰会

    近日,Linux内核领域顶级技术峰会——LSF/MM/BPF 2026在克罗地亚萨格勒布举行。大会聚焦Linux内核存储、文件系统、内存管理以及BPF等关键技术方向,吸引了来自全球开源
    的头像 发表于 05-14 11:08 533次阅读

    Vector PC-lint Plus新增项目级静态函数调用图输出功能

    从2025SP1版本起,PC-lint Plus新增项目级静态函数调用图(Static Function Call Graph)输出功能。
    的头像 发表于 05-08 16:00 199次阅读
    Vector PC-lint Plus新增项目级静态<b class='flag-5'>函数</b><b class='flag-5'>调用</b>图输出功能

    如何理解Linux内核中的PCIe驱动

    我们习惯了用 Verilog 去死磕 PCIe 的底层协议状态机。但一旦越过硬件边界来到操作系统层面,Linux 内核是如何接管并驱动这些 PCI/PCIe 设备的呢?由于不同的 CPU 架构实现了
    的头像 发表于 04-11 17:22 1402次阅读

    Linux内核驱动开发的技术核心精要

    根据平台选择。 五、调试与移植:内核开发的双翼 调试工具链决定问题定位效率:printk基础但易影响时序;Oops/Panic信息是分析崩溃的关键;ftrace可追踪函数调用、中断延迟
    发表于 03-10 13:56

    Linux内核伙伴系统内存申请函数详解:从原理到实战

    Linux 内核中,内存管理是整个系统稳定运行的基石,而伙伴系统(Buddy System) 作为内核物理内存分配的核心机制,更是驱动开发、内核模块开发的必备知识点。它通过 "2
    的头像 发表于 02-10 16:58 3771次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>伙伴系统内存申请<b class='flag-5'>函数</b>详解:从原理到实战

    【「Linux 设备驱动开发(第 2 版)」阅读体验】+读深入理解Linux内核内存分配

    *kmalloc(size_t size, int flags);”函数。 通过对这章的学习,深刻体会到Linux内核的内存分配管理机制博大精深,有些知识点还是初次触碰到,当然也有一些耳熟能详的概念,比如“写
    发表于 01-16 20:05

    【「Linux 设备驱动开发(第 2 版)」阅读体验】Linux内核开发基础

    ,本文介绍Linux内核开发基础 处理内核的核心辅助函数 Linux内核加锁机制和共享资源 无论
    发表于 01-12 22:45

    【「Linux 设备驱动开发(第 2 版)」阅读体验】+读内核处理的核心辅助函数

    理解Linux内核时间管理”知识点。 Linux内核时间管理部分,作者图文并茂,详细介绍了其实现流程。 通过对这几章节的学习,体会到作者在知识点介绍方面承上启下,层层深入,由常见的
    发表于 01-10 22:08

    ElfBoard嵌入式教育科普|Linux系统I/O接口:Open函数详解

    1.函数概述open()是Linux/Unix内核提供的底层系统调用,核心功能是打开或创建文件。成功调用后,
    的头像 发表于 12-29 11:41 1398次阅读
    ElfBoard嵌入式教育科普|<b class='flag-5'>Linux</b>系统I/O接口:Open<b class='flag-5'>函数</b>详解

    基于 DR1M90 的 Linux-RT 内核开发:从编译配置到 GPIO / 按键应用实现(1)

    本手册由创龙科技研发,针对 DR1M90,详述 Linux-RT 实时内核开发:含实时性测试(LinuxLinux-RT 对比、CPU 空载 / 满负荷 / 隔离状态测试)、
    的头像 发表于 12-02 10:38 1415次阅读
    基于 DR1M90 的 <b class='flag-5'>Linux</b>-RT <b class='flag-5'>内核</b>开发:从编译配置到 GPIO / 按键应用实现(1)

    Linux内核模块的加载机制

    使用insmod或modprobe命令来加载模块。insmod是直接加载,而modprobe会处理依赖关系。 2、如何工作 那内核模块具体是怎么工作的呢?当执行insmod时,会调用系统调用
    发表于 11-25 06:59

    Linux内核printk日志级别全解析:从参数解读到实操配置

    一、开篇:一个命令引出的核心问题 在 Linux 终端执行 cat /proc/sys/kernel/printk,你可能会看到这样的输出: 这串数字不是随机的,而是内核日志系统的“核心配置开关
    的头像 发表于 11-20 15:54 2086次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>printk日志级别全解析:从参数解读到实操配置

    探索操作系统底层的关键接口

      在linux中,将程序的运行空间分为内核空间与用户空间(内核态和用户态),在逻辑上它们之间是相互隔离的,因此用户程序不能访问内核数据,也无法使用
    的头像 发表于 11-08 12:42 933次阅读

    深入了解系统调用API:探索操作系统底层的关键接口

    ,也无法使用内核函数。当用户进程必须访问内核或使用某个内核函数时,就得使用系统调用(System
    的头像 发表于 11-03 09:20 970次阅读

    如何配置和验证Linux内核参数

    Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要。合理的参数调整可以显著提升网络性能、系统稳定性及资源利用率。然而,仅仅修改参数是不够的,如何验证这些参数是否生效同样关键。
    的头像 发表于 05-29 17:40 1488次阅读