搜档网
当前位置:搜档网 › Linux内核调试工具Kprobe机制的研究

Linux内核调试工具Kprobe机制的研究

Linux内核调试工具Kprobe机制的研究
Linux内核调试工具Kprobe机制的研究

Linux内核调试工具Kprobe机制的研究

李清干* 邵作之

(华北电力大学计算机科学与技术学院,北京 102206)

摘 要:在传统内核调试过程中,我们经常使用print k作为内核调试的一种方法,但这种方法执行速度相对较慢,在对响应时间要求比较严格的内核控制路径(如中断)中不宜采用它。Kprobe(K erne l probe)与2 6内核结合起来提供了一个动态插入pri n t k的轻量级、无干扰而且强大的装置,使用K probe不需要经常重新引导和重新编译内核就可以完成这一任务。本文重点介绍K probe调试机制原理以及同内核接口。

关键词:L inux内核;K probe;探测点

一、Kp robe机制简介

K probe是IB M公司开发的一个轻量级调试工具,它允许内核运行时通过加载模块设置探测器,内核运行到探测点时便执行其相应的处理函数,这是以前的所有工具都做不到的。K probe作为一个动态地收集调试和性能信息的工具,它从Dprobe项目派生而来,是一种非破坏性工具,用户用它几乎可以跟踪任何函数或被执行的指令以及一些异步事件(如ti m er)。它的基本工作机制是:用户指定一个探测点,并把一个用户定义的处理函数关联到该探测点,当内核执行到该探测点时,相应的关联函数被执行,然后继续执行正常的代码路径。使用K probe可以轻松地通过收集处理器寄存器和全局数据结构等调试信息。开发者甚至可以使用K probe来修改寄存器值和全局数据结构的值。

K probe实现了三种类型的探测点:kprobes、j probes和kretprobes(也叫返回探测点)。kprobes是可以被插入到内核的任何指令位置的探测点,j probes则只能被插入到一个内核函数的入口,而kre t probes则是在指定的内核函数返回时才被执行。这三种类型可以用在不同情况的上下文中。

二、Kp robe机制实现原理

当安装一个kprobes探测点时,K probe首先备份被探测的指令,然后使用断点指令(即在i386和x86_64的i nt3指令)来取代被探测指令的头一个或几个字节。当CPU执行到探测点时,将因运行断点指令而执行trap操作,那将导致保存CPU的寄存器,调用相应的trap处理函数,而trap 处理函数将调用相应的no tifi er_call_cha i n(内核中一种异步工作机制)中注册的所有notifier函数,kprobe正是通过向trap对应的no tifi er_ca ll_cha i n注册关联到探测点的处理函数来实现探测处理的。当kprobe注册的notifier被执行时,它首先执行关联到探测点的pre_handler函数,并把相应的kprobe struct和保存的寄存器作为该函数的参数,接着, kprobe单步执行被探测指令的备份,最后,kprobe执行post_hand l e r。等所有这些运行完毕后,紧跟在被探测指令后的指令流j probe通过注册kprobes在被探测函数入口来实现,它能无缝地访问被探测函数的参数。j probe处理函数应当和被探测函数有同样的原型,而且该处理函数在函数末必须调用kprobe提供的函数jprobe_re t urn()。当执行到该探测点时,kprobe备份CPU寄存器和栈的一些部分,然后修改指令寄存器指向j probe处理函数,当执行该j probe处理函数时,寄存器和栈内容与执行真正的被探测函数一模一样,因此它不需要任何特别的处理就能访问函数参数,在该处理函数执行到最后时,它调用j probe_ret u rn(),那导致寄存器和栈恢复到执行探测点时的状态,因此被探测函数能被正常运行。需要注意,被探测函数的参数可能通过栈传递,也可能通过寄存器传递,但是j probe对于两种情况都能工作,因为它既备份了栈,又备份了寄存器,当然,前提是j probe处理函数原型必须与被探测函数完全一样。

kretprobe也使用了kprobes来实现,当用户调用reg ister_kretprobe()时,kprobe在被探测函数的入口建立了一个探测点,当执行到探测点时,kprobe保存了被探测函数的返回地址并取代返回地址为一个tra m po li ne的地址, kprobe在初始化时,定义了该tra m po line并且为该tra m po li ne 注册了一个kprobe,当被探测函数执行它的返回指令时,控制传递到该trampo li ne,因此kprobe已经注册的对应于tra m po li ne的处理函数将被执行,而该处理函数会调用用户关联到该kre t probe上的处理函数,处理完毕后,设置指令寄存器指向已经备份的函数返回地址,因而原来的函数返回被正常执行。

被探测函数的返回地址保存在类型为kretprobe_i n stance的变量中,结构kretprobe的m axacti v e字段指定了被探测函数可以被同时探测的实例数,函数reg i ster_kretprobe ()将预分配指定数量的kretprobe_instance。如果被探测函数是非递归的并且调用时已经保持了自旋锁(sp i nlock),那么m axacti v e为1就足够了;如果被探测函数是非递归的且运行时是抢占失效的,那么m ax acti ve为NR_CPU S就可以

349

中国电力教育 2008年研究综述与技术论坛专刊*作者简介:李清干,男,华北电力大学计算机科学与技术学院硕士研究生。

了;如果m axacti ve被设置为小于等于0,它被设置到缺省值(如果抢占使能,即配置了CON F I G_PREE M PT,缺省值为10和2*NR_CPU S中的最大值,否则缺省值为NR_ CPU S)。

如果m axactive被设置的太小了,一些探测点的执行可能被丢失,但是不影响系统的正常运行,在结构kretprobe 中n m i ssed字段将记录被丢失的探测点执行数,它在返回探测点被注册时设置为0,每次当执行探测函数而没有kret probe_i nstance可用时,它就加1。

三、Kp robe接口函数注册与卸载

K probe为每一类型的探测点提供了注册和卸载函数。

1 reg ist e r_kprobe

它用于注册一个kprobes类型的探测点,其函数原型为:

int regis t er_kprobe(struc t kprobe*kp);

为了使用该函数,用户需要在源文件中包含头文件li nux/kprobes h。该函数的参数是struct kprobe类型的指针。

其中addr指定探测点的位置,pre_handler指定执行到探测点时执行的处理函数,post_handler指定执行完探测点后执行的处理函数,fault_handler指定错误处理函数,当在执行pre_handler、post_handler以及被探测函数期间发生错误时,它会被调用。在调用该注册函数前,用户必须先设置好struct kprobe的这些字段,用户可以指定任何处理函数为NU LL。

该注册函数会在kp->addr地址处注册一个kprobes类型的探测点,当执行到该探测点时,将调用函数kp-> pre_hand l e r,执行完被探测函数后,将调用kp->post_ handler。如果在执行kp->pre_handler或kp->po st_ handler时或在单步跟踪被探测函数期间发生错误,将调用kp->fault_handler。该函数成功时返回0,否则返回负的错误码。

探测点处理函数pre_handler的原型如下:

int pre_handler(struct kprobe*p,struct pt_regs*r egs)

用户必须按照该原型参数格式定义自己的pre_handler,当然函数名取决于用户自己。参数p就是指向该处理函数关联到的kprobes探测点的指针,可以在该函数内部引用该结构的任何字段,就如同在使用调用reg ister_kprobe时传递的那个参数。参数reg s指向运行到探测点时保存的寄存器内容。kprobe负责在调用pre_hand ler时传递这些参数,用户不必关心,只是要知道在该函数内就能访问这些内容,一般地,它应当始终返回0。

探测点处理函数post_handler的原型如下:

void post_hand l e r(s truc t kprobe*p,s truc t pt_regs*r egs, uns i g ned long fl a gs)

前两个参数与pre_handler相同,最后一个参数flags总是0。

错误处理函数fau lt_hand l er的原型如下:

int fault_handler(struct kprobe*p,struct pt_regs*regs,int trapnr)

前两个参数与pre_handler相同,第三个参数trapnr是与错误处理相关的架构依赖的trap号(例如,对于i386,通常的保护错误是13,而页失效错误是14)。如果成功地处理了异常,它应当返回1。

2 reg ist e r_j p robe

该函数用于注册jprobes类型的探测点,它的原型如下:

int regis t er_jprobe(struct jpr obe*jp)

为了使用该函数,用户需要在源文件中包含头文件li nux/kprobes h。

用户在调用该注册函数前需要定义一个struct j probe类型的变量并设置它的kp addr和entry字段,kp addr指定探测点的位置,它必须是被探测函数的第一条指令的地址, entry指定探测点的处理函数,该处理函数的参数表和返回类型应当与被探测函数完全相同,而且它必须正好在返回前调用jprobe_re t urn()。如果被探测函数被声明为as m li nkag e、fastcall或影响参数传递的任何其他形式,那么相应的处理函数也必须声明为相应的形式。

该注册函数在j p->kp addr注册一个j probes类型的探测点,当内核运行到该探测点时,j p->entry指定的函数会被执行。如果成功,该函数返回0,否则返回负的错误码。

3 reg ist e r_kre t p robe

该函数用于注册类型为kre tprobes的探测点,它的原型如下:

int regis t er_kret p r obe(s truc t kretprobe*rp)

为了使用该函数,用户需要在源文件中包含li nux/ kprobes h。

该注册函数的参数为struct kre tprobe类型的指针,用户在调用该函数前必须定义一个struct kretprobe的变量并设置它的kp addr、hand l er以及m axac ti ve字段,kp addr指定探测点的位置,hand l e r指定探测点的处理函数,maxactive指定可以同时运行的最大处理函数实例数,它应当被恰当设置,否则可能丢失探测点的某些运行。

该注册函数在地址rp->kp addr注册一个k retprobe类型的探测点,当被探测函数返回时,rp->hand l e r会被调用。如果成功,它返回0,否则返回负的错误码。

kretprobe处理函数的原型如下:

int kret p r obe_ha ndler(str uct kretpr obe_i n st a nce*r,i struc t pt_ regs*r egs)

参数regs指向保存的寄存器,ri指向类型为struct kret probe_i nstance的变量,该结构的ret_addr字段表示返回地址,rp指向相应的kre t probe_instance变量,task字段指向相应的task_struc t。结构struct kretprobe_i nstance是注册函数reg i ster_kretprobe根据用户指定的m axacti ve值来分配的, kprobe负责在调用kretprobe处理函数时传递相应的kretpro be_i nstance。

4 un reg ist e r*p robe

对应于每一个注册函数,有相应的卸载函数。

350

void unreg i s ter_kprobe(s truc t kprobe*kp)

void unreg i s ter_j p robe(struct jprobe*jp)

void unreg i s ter_kretprobe(struct kretprobe*rp)

上面是对应与三种探测点类型的卸载函数,当使用探测点的模块卸载或需要卸载已经注册的探测点时,需要使用相应的卸载函数来卸载已经注册的探测点,kp,jp和rp 分别为指向结构struct kprobe、struc t jprobe和struct kretprobe 的指针,它们应当指向调用对应的注册函数时使用的那个结构,也就说注册和卸载必须针对同样的探测点,否则会导致系统崩溃。这些卸载函数可以在注册后的任何时刻调用。

四、结束语

本文主要介绍了收集和调试内核的K probe工具工作机制,它可以将断点插入到正在运行的内核之中。使用K probe的好处有很多。不需要重新编译和重新引导内核就可以插入pri n t k,为了进行调试,可以记录处理器寄存器的日志,甚至进行修改 不会干扰系统。类似地,可以轻松地收集处理器寄存器和全局数据结构等调试信息,开发者可以使用K probe来修改寄存器值和全局数据结构的值。您甚至可以使用K probe调试S M P系统上的竞态条件 避免了自己重新编译和重新引导的所有麻烦,内核调试将比以往更为快速和简单。

参考文献:

[1]陈燕晖,罗宇.L i nux内核数据采集的一种有效方法.计算机应用与软件,2006,6.

[2]Dan i el P.Bovet,M arco Cesat,i Unders t and i ng t h e L i nux K ern e,l 2nd Ed iti on,OpR eill y,2002.

[3]Kprob e project.h tt p://www-124.i bm.co m.

[4]L i nux T race Too l k itP roj ect,h tt p://www.opersys.co m/LTT/.

(上接第348页)

硬件(IB M370)和原有操作系统(VM/370)的结构都支持虚拟机。采用虚拟机法增强操作系统的安全性时,硬件特性对虚拟机的实现非常关键,它要求原系统的硬件和结构都要支持虚拟机,因此用这种方法开发安全操作系统的局限性很大。

2 改进/增强法

在现有操作系统的基础上,对其内核和应用程序进行面向安全策略的分析,然后加入安全机制,经改造、开发后的安全操作系统基本上保持原操作系统的用户接口界面。

由于改进/增强法是在现有系统的基础上开发增强安全性的,受其体系结构和现有应用程序的限制,所以很难达到很高(如B3级以上)的安全级别。但这种方法不破坏原系统的体系结构,开发代价小,且能很好地保持原操作系统的用户接口界面和系统效率。

3 仿真法

对现有操作系统的内核做面向安全策略的修改,然后在安全内核与原有操作系统用户接口界面中间,再编写一层仿真程序。这样,在建立安全内核时,可以不必受现有的应用程序的限制,且可以完全自由地定义操作系统的仿真程序与安全核之间的接口。但采用这种方法要同时设计仿真程序和安全内核,还要受顶层。

操作系统接口的限制。另外,根据安全策略,有些操作系统的接口功能不安全,从而不能仿真,有些接口尽管安全,但仿真实现特别困难。

三、总结

L inux安全操作系统实现了多级安全保护,即在原有的基础上增加了强制访问控制、安全审计、特权管理等安全模块,这样就使系统的安全性能得到增强。本文在原理和技术实现上都给与了详细的分析。

参考文献:

[1]杨沿航,孙冰心.操作系统的安全策略.东北林业大学学报.

[2]王亚辉,衷克定,于鹦.一种基LI NUX操作系统的安全增强实现思路.计算机应用与软件.

[3]张衡,张毓森,路卫东.L i nux安全增强系统中能力机制的实现与评估[J].系统仿真学报,2004,16(1):79-81.

351

Linux内核崩溃原因分析及错误跟踪技术

Linux内核崩溃原因分析及错误跟踪技术 随着嵌入式Linux系统的广泛应用,对系统的可靠性提出了更高的要求,尤其是涉及到生命财产等重要领域,要求系统达到安全完整性等级3级以上[1],故障率(每小时出现危险故障的可能性)为10-7以下,相当于系统的平均故障间隔时间(MTBF)至少要达到1141年以上,因此提高系统可靠性已成为一项艰巨的任务。对某公司在工业领域14 878个控制器系统的应用调查表明,从2004年初到2007年9月底,随着硬软件的不断改进,根据错误报告统计的故障率已降低到2004年的五分之一以下,但查找错误的时间却增加到原来的3倍以上。 这种解决问题所需时间呈上升的趋势固然有软件问题,但缺乏必要的手段以辅助解决问题才是主要的原因。通过对故障的统计跟踪发现,难以解决的软件错误和从发现到解决耗时较长的软件错误都集中在操作系统的核心部分,这其中又有很大比例集中在驱动程序部分[2]。因此,错误跟踪技术被看成是提高系统安全完整性等级的一个重要措施[1],大多数现代操作系统均为发展提供了操作系统内核“崩溃转储”机制,即在软件系统宕机时,将内存内容保存到磁盘[3],或者通过网络发送到故障服务器[3],或者直接启动内核调试器[4]等,以供事后分析改进。 基于Linux操作系统内核的崩溃转储机制近年来有以下几种: (1) LKCD(Linux Kernel Crash Dump)机制[3]; (2) KDUMP(Linux Kernel Dump)机制[4]; (3) KDB机制[5]; (4) KGDB机制[6]。 综合上述几种机制可以发现,这四种机制之间有以下三个共同点: (1) 适用于为运算资源丰富、存储空间充足的应用场合; (2) 发生系统崩溃后恢复时间无严格要求; (3) 主要针对较通用的硬件平台,如X86平台。 在嵌入式应用场合想要直接使用上列机制中的某一种,却遇到以下三个难点无法解决: (1) 存储空间不足 嵌入式系统一般采用Flash作为存储器,而Flash容量有限,且可能远远小于嵌入式系统中的内存容量。因此将全部内存内容保存到Flash不可行。

Tornado IDE与VxSim目标仿真环境

实验六 Tornado IDE 与 VxSim目标仿真环 境 6.1 实验目的 熟悉 Tornado开发环境,编辑、编译、下载、调试程序,熟练使用 GNU/Diab 编译器、 Cross Wind/Wind Shell 调试工具、Brower/Wind View 分析工具、VxSim目标仿真器,了解嵌 入式开发的基本方法和过程。 6.2 实验内容 (1) Hello World和 Goodbye World实验。使用 Tornado集成开发环境新建一个工作空间 和工程,通过编辑器编辑程序,并使用工程工具的 GNU编译程序,将程序下载到运行在主 机上的 VxWorks 目标仿真器,使用Wind Shell 运行程序, (2) 通过调试 Tornado 自带的 cobble 程序,掌握使用 Browse 观察目标仿真器的内存使 用情况,使用 Wind View图形化地跟踪监视示例程序的执行流程,使用Debugger 调试运行 时应用程序的错误。 6.3 实验软硬件环境 硬件: 主机: PIII800 ,内存 256M ,硬盘 30G 及以上 目标机:VxSim目标仿真器 软件: 主机: Windows2000/XP,Tornado2.2 目标机:VxWorks5.5 6.4 实验预备知识 Tornado 软总线体系结构,Tornado的工具集组成及其功能。 6.5 实验项目与步骤 6.5.1 Hello World 与 Goodbye World 实验 在本实验中,要求使用 Tornado工具编写一个“Hello World”的程序。该程序中有两个 函数,可以在 Tornado的 Wind Shell 工具中输入这两个函数的名称来启动这两个函数执行。 步骤见下。

探究linux内核,超详细解析子系统

探究linux内核,超详细解析子系统 Perface 前面已经写过一篇《嵌入式linux内核的五个子系统》,概括性比较强,也比较简略,现在对其进行补充说明。 仅留此笔记,待日后查看及补充!Linux内核的子系统 内核是操作系统的核心。Linux内核提供很多基本功能,如虚拟内存、多任务、共享库、需求加载、共享写时拷贝(Copy-On-Write)以及网络功能等。增加各种不同功能导致内核代码不断增加。 Linux内核把不同功能分成不同的子系统的方法,通过一种整体的结构把各种功能集合在一起,提高了工作效率。同时还提供动态加载模块的方式,为动态修改内核功能提供了灵活性。系统调用接口用户程序通过软件中断后,调用系统内核提供的功能,这个在用户空间和内核提供的服务之间的接口称为系统调用。系统调用是Linux内核提供的,用户空间无法直接使用系统调用。在用户进程使用系统调用必须跨越应用程序和内核的界限。Linux内核向用户提供了统一的系统调用接口,但是在不同处理器上系统调用的方法

各不相同。Linux内核提供了大量的系统调用,现在从系统 调用的基本原理出发探究Linux系统调用的方法。这是在一个用户进程中通过GNU C库进行的系统调用示意图,系 统调用通过同一个入口点传入内核。以i386体系结构为例,约定使用EAX寄存器标记系统调用。 当加载了系统C库调用的索引和参数时,就会调用0x80软件中断,它将执行system_call函数,这个函数按照EAX 寄存器内容的标示处理所有的系统调用。经过几个单元测试,会使用EAX寄存器的内容的索引查system_call_table表得到系统调用的入口,然后执行系统调用。从系统调用返回后,最终执行system_exit,并调用resume_userspace函数返回用户空间。 linux内核系统调用的核心是系统多路分解表。最终通过EAX寄存器的系统调用标识和索引值从对应的系统调用表 中查出对应系统调用的入口地址,然后执行系统调用。 linux系统调用并不单层的调用关系,有的系统调用会由

关于Linux 内核中五个主要子系统的介绍

关于Linux 内核中五个主要子系统的介绍 发布时间:2008.01.02 06:23来源:赛迪网作者:sixth 1.进程调度(SCHED):控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可运行进程实际上是仅等待CPU资源的进程,如果某个进程在等待其它资源,则该进程是不可运行进程。Linux使用了比较简单的基于优先级的进程调度算法选择新的进程。 2.内存管理(MM)允许多个进程安全的共享主内存区域。Linux的内存管理支持虚拟内存,即在计算机中运行的程序,其代码,数据,堆栈的总量可以超过实际内存的大小,操作系统只是把当前使用的程序块保留在内存中,其余的程序块则保留在磁盘中。必要时,操作系统负责在磁盘和内存间交换程序块。内存管理从逻辑上分为硬件无关部分和硬件有关部分。硬件无关部分提供了进程的映射和逻辑内存的对换;硬件相关的部分为内存管理硬件提供了虚拟接口。 3.虚拟文件系统(VirtualFileSystem,VFS)隐藏了各种硬件的具体细节,为所有的设备提供了统一的接口,VFS提供了多达数十种不同的文件系统。虚拟文件系统可以分为逻辑文件系统和设备驱动程序。逻辑文件系统指Linux所支持的文件系统,如ext2,fat等,设备驱动程序指为每一种硬件控制器所编写的设备驱动程序模块。 4.网络接口(NET)提供了对各种网络标准的存取和各种网络硬件的支持。网络接口可分为网络协议和网络驱动程序。网络协议部分负责实现每一种可能的网络传输协议。网络设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。 5.进程间通讯(IPC) 支持进程间各种通信机制。处于中心位置的进程调度,所有其它的子系统都依赖它,因为每个子系统都需要挂起或恢复进程。一般情况下,当一个进程等待硬件操作完成时,它被挂起;当操作真正完成时,进程被恢复执行。例如,当一个进程通过网络发送一条消息时,网络接口需要挂起发送进程,直到硬件成功地完成消息的发送,当消息被成功的发送出去以后,网络接口给进程返回一个代码,表示操作的成功或失败。其他子系统以相似的理由依赖于进程调度。

linux内核IMQ源码实现分析

本文档的Copyleft归wwwlkk所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性,严禁用于任何商业用途。 E-mail: wwwlkk@https://www.sodocs.net/doc/9a10582552.html, 来源: https://www.sodocs.net/doc/9a10582552.html,/?business&aid=6&un=wwwlkk#7 linux2.6.35内核IMQ源码实现分析 (1)数据包截留并重新注入协议栈技术 (1) (2)及时处理数据包技术 (2) (3)IMQ设备数据包重新注入协议栈流程 (4) (4)IMQ截留数据包流程 (4) (5)IMQ在软中断中及时将数据包重新注入协议栈 (7) (6)结束语 (9) 前言:IMQ用于入口流量整形和全局的流量控制,IMQ的配置是很简单的,但很少人分析过IMQ的内核实现,网络上也没有IMQ的源码分析文档,为了搞清楚IMQ的性能,稳定性,以及借鉴IMQ的技术,本文分析了IMQ的内核实现机制。 首先揭示IMQ的核心技术: 1.如何从协议栈中截留数据包,并能把数据包重新注入协议栈。 2.如何做到及时的将数据包重新注入协议栈。 实际上linux的标准内核已经解决了以上2个技术难点,第1个技术可以在NF_QUEUE机制中看到,第二个技术可以在发包软中断中看到。下面先介绍这2个技术。 (1)数据包截留并重新注入协议栈技术

(2)及时处理数据包技术 QoS有个技术难点:将数据包入队,然后发送队列中合适的数据包,那么如何做到队列中的数

激活状态的队列是否能保证队列中的数据包被及时的发送吗?接下来看一下,激活状态的队列的 证了数据包会被及时的发送。 这是linux内核发送软中断的机制,IMQ就是利用了这个机制,不同点在于:正常的发送队列是将数据包发送给网卡驱动,而IMQ队列是将数据包发送给okfn函数。

Linux内核结构详解教程

Linux内核结构详解教程 ─────Linux内核教程 linux内核就像人的心脏,灵魂,指挥中心。 内核是一个操作系统的核心,它负责管理系统的进程,内存,设备驱动程序,文件和网络系统,决定着系统的性能和稳定性。内核以独占的方式执行最底层任务,保证系统正常运行。协调多个并发进程,管理进程使用的内存,使它们相互之间不产生冲突,满足进程访问磁盘的请求等等. 严格说Linux并不能称做一个完整的操作系统.我们安装时通常所说的Linux,是有很多集合组成的.应称为GNU/Linux. 一个Linux内核很少1.2M左右,一张软盘就能放下. 内容基础,语言简短简洁 红联Linux论坛是致力于Linux技术讨论的站点,目前网站收录的文章及教程基本能满足不同水平的朋友学习。 红联Linux门户: https://www.sodocs.net/doc/9a10582552.html, 红联Linux论坛: https://www.sodocs.net/doc/9a10582552.html,/bbs 红联Linux 论坛大全,所有致力点都体现在这 https://www.sodocs.net/doc/9a10582552.html,/bbs/rf/linux/07.htm

目录 Linux内核结构详解 Linux内核主要五个子系统详解 各个子系统之间的依赖关系 系统数据结构 Linux的具体结构 Linux内核源代码 Linux 内核源代码的结构 从何处开始阅读源代码 海量Linux技术文章

Linux内核结构详解 发布时间:2006-11-16 19:05:29 Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。

Linux内核主要五个子系统详解 发布时间:2006-11-16 19:05:54 1.进程调度(SCHED):控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可运行进程实际上是仅等待CPU资源的进程,如果某个进程在等待其它资源,则该进程是不可运行进程。Linux使用了比较简单的基于优先级的进程调度算法选择新的进程。 2.内存管理(MM)允许多个进程安全的共享主内存区域。Linux的内存管理支持虚拟内存,即在计算机中运行的程序,其代码,数据,堆栈的总量可以超过实际内存的大小,操作系统只是把当前使用的程序块保留在内存中,其余的程序块则保留在磁盘中。必要时,操作系统负责在磁盘和内存间交换程序块。内存管理从逻辑上分为硬件无关部分和硬件有关部分。硬件无关部分提供了进程的映射和逻辑内存的对换;硬件相关的部分为内存管理硬件提供了虚拟接口。 3.虚拟文件系统(VirtualFileSystem,VFS)隐藏了各种硬件的具体细节,为所有的设备提供了统一的接口,VFS提供了多达数十种不同的文件系统。虚拟文件系统可以分为逻辑文件系统和设备驱动程序。逻辑文件系统指Linux所支持的文件系统,如ext2,fat等,设备驱动程序指为每一种硬件控制器所编写的设备驱动程序模块。 4.网络接口(NET)提供了对各种网络标准的存取和各种网络硬件的支持。网络接口可分为网络协议和网络驱动程序。网络协议部分负责实现每一种可能的网络传输协议。网络设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。 5.进程间通讯(IPC) 支持进程间各种通信机制。 处于中心位置的进程调度,所有其它的子系统都依赖它,因为每个子系统都需要挂起或恢复进程。一般情况下,当一个进程等待硬件操作完成时,它被挂起;当操作真正完成时,进程被恢复执行。例如,当一个进程通过网络发送一条消息时,网络接口需要挂起发送进程,直到硬件成功地完成消息的发送,当消息被成功的发送出去以后,网络接口给进程返回一个代码,表示操作的成功或失败。其他子系统以相似的理由依赖于进程调度。

Linux内核移植开发手册

江苏中科龙梦科技有限公司 Linux内核移植开发手册 修 订 记 录 项 次 修订日期 版 本修订內容修订者审 核 1 2009‐02‐04 0.1 初版发行陶宏亮, 胡洪兵 2 2009‐11‐20 0.2 删除一些 多余文字 陶宏亮, 胡洪兵

DISCLAIMER THIS DOCUMENTATION IS PROVIDED FOR USE WITH LEMOTE PRODUCTS. NO LICENSE TO LEMOTE PROPERTY RIGHTS IS GRANTED. LEMOTE ASSUMES NO LIABILITY, PROVIDES NO WARRANTY EITHER EXPRESSED OR IMPLIED RELATING TO THE USAGE, OR INTELLECTUAL PROPERTY RIGHT INFRINGEMENT EXCEPT AS PROVIDED FOR BY LEMOTE TERMS AND CONDITIONS OF SALE. LEMOTE PRODUCTS ARE NOT DESIGNED FOR AND SHOULD NOT BE USED IN ANY MEDICAL OR LIFE SUSTAINING OR SUPPORTING EQUIPMENT. ALL INFORMATION IN THIS DOCUMENT SHOULD BE TREATED AS PRELIMINARY. LEMOTE MAY MAKE CHANGES TO THIS DOCUMENT WITHOUT NOTICE. ANYONE RELYING ON THIS DOCUMENTATION SHOULD CONTACT LEMOTE FOR THE CURRENT DOCUMENTATION AND ERRATA. JIANGSU LEMOTE TECHNOLOGY CORPORATION LIMITED MENGLAN INDUSTRIAL PARK,YUSHAN,CHANGSHU CITY,JIANGSU PROVINCE,CHINA Tel: 0512‐52308661 Fax: 0512‐52308688 Http: //https://www.sodocs.net/doc/9a10582552.html,

浅谈Tornado2.2下程序调试

浅谈Tornado2.2下程序调试 “调试一段程序的难度是写出这段程序的难度的两倍,因此,如果你的代码尽可能清楚,那么你就不用费力的调试它”-- Brian W. Kernighan “有时周一宁愿休息而不是花一周余下的时间调试周一的代码” -- Christopher Thompson ….. ….. 调试对于软件的成败至关重要,正确使用恰当的调试工具可以提高发现和改正错误的效率。 一、调试前的准备工作 1、保证目标机跟主机能网络正常通信。如果tornado是装在虚拟机中,则要保 证虚拟机跟目标机能网络通信。用ping xx.xx.xx.xx –l 1500命令。之所以后面要加-l 1500是为了保证最大包也能ping通,如果不加-l 则为ARP包,ARP包只有64个字节。在网络通信中会出现小包能ping通,大包ping不通的情况。 2、保证WDB为Ready状态 图1 如果WDB为unReady状态,很可能是WDB的组件没有加。 二、配置Target Server Target Server是Tornado集成交叉开发环境中最重要的工具。这个工具负责主机与目标机的连接,为其他的工具使用提供通信桥梁。 点击”Tools->Targer Server->configure”。出现如下图2所示:

图2 Target server配置界面 配置界面中Targer Server要填入主机的IP地址,Targer Server PropertiesBack End(后端)默认选择wdbrpc ,它是最常用的连接类型,其支持任意种IP连接(如以太网)。Target Name/Ip Address需要填入目标机的IP地址。主机和目标机的IP地址可以在bootrom起来后看到,如图3所示。 图3 bootrom启动打印 Targer Server Properties 之Core File and Symbols,在File选项中选择主机vxworks镜像的路径,如图4所示。

嵌入式Linux之Kernel(裁减移植)启动调试、打印技术 printascii(补充)、内核调试

嵌入式系统搭建过程中,对于系统平台搭建工程师在完成Bootloader 的调试之后就进入Kernel 裁减移植的阶段,其中最重要的一步是Kernel 启动的调试,在调试Kernel 过程中通常遇到最常见的问题是启动异常: Uncompressing Linux............................................................ ........................... done, booting the kernel.( 挂死在此处) 注意:这里是arch/arm/boot/compressed/head.S的解压过程,调用了decompress_kernel()(同目录下的misc.c)->include/asm-arm/arch-xxx/uncompress.h的putc()实现。这是在uboot中初始化的,用的是物理地址,因为此时内核还没有起来。 而printascii则是调用了汇编。printascii()位于arch/arm/kernel/debug.S,他需要调用虚拟地址,此虚拟地址通过machine_start提供,而相关的宏在include/asm/arch-xxx/debug-macro.S实现,这下明白了。 10-05-14添加:debug.s里面需要判断一下当前是否打开了mmu,然后指定uart的基址。在解压阶段的head.s,mmu是1:1映射,目的是加快速度。到了内核的head.s,就是真正的mmu了,此时就是虚拟地址了。 导致驱动异常(启动挂死)的原因有很多,如基于EVM 板的硬件做了修改(如更改了FLASH 空间大小、地址和型号,更改了SDRAM 、DDR SDRAM 空间大小、地址和型号,更改了晶振频率等),板卡ID号不支持等。那么如何进行调试那,其实有两种调试技术比较有效。 Kernel 启动调试技术- 使用printascii() 函数跟踪start_kernel() 有没运行,在booting the kernel 之后Kernel 最先执行的是start_kernel() 函数,确认start_kernel() 有否执行就是在其开始代码段添加printascii("start_kernel …") ,如果串口没有打印出start_kernel …,说明start_kernel() 没有运行,那么可能的原因有Bootloader 配置的启动参数错误、 Kernel 加载到(DDR) SDRAM 的地址不正确, Kernel 编译时指定的(DDR) SDRAM 运行地址不正确等。这样就需要一项一项排查错误,当错误被排查完毕,通常打印出start_kernel …是种必然,如果打印出这仪信息说明 Kernel已进入到start_kernel() 执行,如果此时有串口启动打印就比较成功了,如果仍然没有打印启动信息,就需要另外一种调试技术。 附代码修改:init/main.c <<- … extern void printascii(const char*); // Modify asmlinkage void __init start_kernel(void)

Linux内核分析-网络[五]:网桥

看完了路由表,重新回到netif_receive_skb ()函数,在提交给上层协议处理前,会执行下面一句,这就是网桥的相关操作,也是这篇要讲解的容。 view plaincopy to clipboardprint? 1. s kb = handle_bridge(skb, &pt_prev, &ret, orig_dev); 网桥可以简单理解为交换机,以下图为例,一台linux机器可以看作网桥和路由的结合,网桥将物理上的两个局域网LAN1、LAN2当作一个局域网处理,路由连接了两个子网1.0和2.0。从eth0和eth1网卡收到的报文在Bridge模块中会被处理成是由Bridge收到的,因此Bridge也相当于一个虚拟网卡。 STP五种状态 DISABLED BLOCKING LISTENING LEARNING FORWARDING 创建新的网桥br_add_bridge [net\bridge\br_if.c] 当使用SIOCBRADDBR调用ioctl时,会创建新的网桥br_add_bridge。 首先是创建新的网桥: view plaincopy to clipboardprint?

1. d ev = new_bridge_dev(net, name); 然后设置dev->dev.type为br_type,而br_type是个全局变量,只初始化了一个名字变量 view plaincopy to clipboardprint? 1. S ET_NETDEV_DEVTYPE(dev, &br_type); 2. s tatic struct device_type br_type = { 3. .name = "bridge", 4. }; 然后注册新创建的设备dev,网桥就相当一个虚拟网卡设备,注册过的设备用ifconfig 就可查看到: view plaincopy to clipboardprint? 1. r et = register_netdevice(dev); 最后在sysfs文件系统中也创建相应项,便于查看和管理: view plaincopy to clipboardprint? 1. r et = br_sysfs_addbr(dev); 将端口加入网桥br_add_if() [net\bridge\br_if.c] 当使用SIOCBRADDIF调用ioctl时,会向网卡加入新的端口br_add_if。 创建新的net_bridge_port p,会从br->port_list中分配一个未用的port_no,p->br会指向br,p->state设为BR_STATE_DISABLED。这里的p实际代表的就是网卡设备。 view plaincopy to clipboardprint? 1. p = new_nbp(br, dev); 将新创建的p加入CAM表中,CAM表是用来记录mac地址与物理端口的对应关系;而刚刚创建了p,因此也要加入CAM表中,并且该表项应是local的[关系如下图],可以看到,CAM表在实现中作为net_bridge的hash表,以addr作为hash值,链入 net_bridge_fdb_entry,再由它的dst指向net_bridge_port。

使用QEMU+GDB调试Linux内核

使用QEMU调试Linux内核 一.使用QEMU安装Ubuntu10.04 1.安装qemu ubuntu下使用sudo apt-get install 安装的qemu版本是0.12.3,该版本中存在bug,使得无法在断点处停下;因此需要在qemu官方网站https://www.sodocs.net/doc/9a10582552.html,/Download上下载最新的版本qemu-0.12.5.tar.gz的源代码包自己进行编译安装: ●Sudo apt-get install zlib1g-dev libsdl-dev ●解压源代码后,进入源代码所在目录执行./confingure ●执行make ●执行sudo make install 2.创建QEMU格式的硬盘 qemu-img create –f qcow2name.img size 例如:qemu-img create –f qcow2 ubuntu10.04.img 4GB 3.在创建的硬盘上安装操作系统 qemu–hdaname.img–cdrom ~/Download/ubuntu10.04.iso –boot d 说明:使用hda指定硬盘镜像,使用CDROM选定光驱。-boot d 指从cdrom启动,-boot a是软盘,-boot c 是硬盘;使用qemu或qemu-system-x86_64(64为机子),有时安装系统会很慢,这是可以考虑使用kvm来代替。 例如:kvm–hda ubuntu10.04.img –cdrom ./ubuntu-10.04.iso -boot

d 4.从已经装好操作系统的硬盘启动 qemu–hda ubuntu10.04.img 5.在64位的主机上要使用qemu-system-x86_64命令来代替qemu 二.自己编译内核 现将Linux的编译调节过程简述为: 1. 下载自己要调试的Linux内核的源代码,这个可以从Linux内 核的官方网站上得到:https://www.sodocs.net/doc/9a10582552.html, 2. 编译内核最主要的便是配置文件.config,为了能够准确的得到 结果(第一次不要求编译时间),将本机的config文件直接拷 贝到解压后的源代码中。 3.然后进行make操作,结束后将产生的bzImage文件拷到boot 目录下,重启,选择自己编译的内核,这样一般不会出问题,但时间较慢,大约编译一次需要40分钟。 3.1以前编译内核是为调试内核服务的,现在做华为的项目, 发现需要在实际的机器上运行自己编译的内核,参考网站: https://www.sodocs.net/doc/9a10582552.html,/tips/compiling-linux-kernel-26.html 4.为了降低编译时间,就需要对配置文件进行裁剪,在配置文件 中有好多是本机不需要的模块,参考: https://www.sodocs.net/doc/9a10582552.html,/Linux/kernel_options.html。另外调试内 核与模块无关,所以辨识为M的直接可以不选。 5.剪裁的时候采用“逐步瘦身”法,先剪裁掉某个或某几个模块, 然后在进行编译,若没错,在进行模块裁剪,这样可以最大程

史上最全linux内核配置详解

对于每一个配置选项,用户可以回答"y"、"m"或"n"。其中"y"表示将相应特性的支持或设备驱动程序编译进内核;"m"表示将相应特性的支持或设备驱动程序编译成可加载模块,在需要时,可由系统或用户自行加入到内核中去;"n"表示内核不提供相应特性或驱动程序的支持。只有<>才能选择M 1. General setup(通用选项) [*]Prompt for development and/or incomplete code/drivers,设置界面中显示还在开发或者还没有完成的代码与驱动,最好选上,许多设备都需要它才能配置。 [ ]Cross-compiler tool prefix,交叉编译工具前缀,如果你要使用交叉编译工具的话输入相关前缀。默认不使用。嵌入式linux更不需要。 [ ]Local version - append to kernel release,自定义版本,也就是uname -r可以看到的版本,可以自行修改,没多大意义。 [ ]Automatically append version information to the version string,自动生成版本信息。这个选项会自动探测你的内核并且生成相应的版本,使之不会和原先的重复。这需要Perl的支持。由于在编译的命令make-kpkg 中我们会加入- –append-to-version 选项来生成自定义版本,所以这里选N。 Kernel compression mode (LZMA),选择压缩方式。 [ ]Support for paging of anonymous memory (swap),交换分区支持,也就是虚拟内存支持,嵌入式不需要。 [*]System V IPC,为进程提供通信机制,这将使系统中各进程间有交换信息与保持同步的能力。有些程序只有在选Y的情况下才能运行,所以不用考虑,这里一定要选。 [*]POSIX Message Queues,这是POSIX的消息队列,它同样是一种IPC(进程间通讯)。建议你最好将它选上。 [*]BSD Process Accounting,允许进程访问内核,将账户信息写入文件中,主要包括进程的创建时间/创建者/内存占用等信息。可以选上,无所谓。 [*]BSD Process Accounting version 3 file format,选用的话统计信息将会以新的格式(V3)写入,注意这个格式和以前的v0/v1/v2 格式不兼容,选不选无所谓。 [ ]Export task/process statistics through netlink (EXPERIMENTAL),通过通用的网络输出工作/进程的相应数据,和BSD不同的是,这些数据在进程运行的时候就可以通过相关命令访问。和BSD类似,数据将在进程结束时送入用户空间。如果不清楚,选N(实验阶段功能,下同)。 [ ]Auditing support,审计功能,某些内核模块需要它(SELINUX),如果不知道,不用选。 [ ]RCU Subsystem,一个高性能的锁机制RCU 子系统,不懂不了解,按默认就行。 [ ]Kernel .config support,将.config配置信息保存在内核中,选上它及它的子项使得其它用户能从/proc/ config.gz中得到内核的配置,选上,重新配置内核时可以利用已有配置Enable access to .config through /proc/config.gz,上一项的子项,可以通过/proc/ config.gz访问.config配置,上一个选的话,建议选上。 (16)Kernel log buffer size (16 => 64KB, 17 => 128KB) ,内核日志缓存的大小,使用默认值即可。12 => 4 KB,13 => 8 KB,14 => 16 KB单处理器,15 => 32 KB多处理器,16 => 64 KB,17 => 128 KB。 [ ]Control Group support(有子项),使用默认即可,不清楚可以不选。 Example debug cgroup subsystem,cgroup子系统调试例子 Namespace cgroup subsystem,cgroup子系统命名空间 Device controller for cgroups,cgroups设备控制器

在vmware虚拟机上调试内核

安装系统(在创建一个新的虚拟机时一定要用IDE硬盘) 1、在vmware上安装一个linux虚拟机(我用的软件版本:vmware 5.5, fedora 6) 从Internet下载源代码 1、linux-2.6.16 2、kgdb-2.6.16 编译内核 1、将kgdb-2.6.16补丁打到Linux内核源码里。 2、编译内核(make menuconfig, make, make modules_install, make install) 在内核配置菜单的Kernel hacking选项中选择kgdb调试项,例如: [*] KGDB: kernel debugging with remote gdb [*] KGDB: Console messages through gdb Method for KGDB communication (KGDB: On generic serial port (8250)) ---> < > KGDB: On ethernet [*] Simple selection of KGDB serial port (115200) Debug serial port baud rate (0) Serial port number for KGDB 3、修改grub.conf 例如: title Fedora Core (2.6.16) root (hd0,0) kernel /vmlinuz-2.6.16 ro root=/dev/VolGroup00/LogVol00 initrd /initrd-2.6.16_debug.img 改为: title Fedora Core (2.6.16) root (hd0,0) kernel /vmlinuz-2.6.16 ro root=/dev/VolGroup00/LogVol00 kgdb8250=0,115200 initrd /initrd-2.6.16_debug.img 4、请检验新编译的内核是否可用。如果不能启动,可能是编译选项没有选好(一直困扰我的问题。实在不行就多选点)。如果没有问题,关闭这个linux虚拟机,进入下一步。

TORNADO环境下的命令行编译文件

Tornado环境下的命令行编译文件 Table of contents目录 T ABLE OF CONTENTS目录 (1) 1TORNADO及其编译工具简介 (2) 2两种编译工具下的C/C++文件编译 (4) 2.1GNU T OOL的编译 (4) 2.2D IAB T OOL的编译 (5) 3MAKEFILE的编译 (6) 3.1特殊变量的定义(以DCN DS45XX项目为例) (6) 3.2MAKEFILE.LOCAL的建立 (7) 3.3命令实现 (8) 4REFERENCE DOCUMENTS参考文献 (9)

1Tornado及其编译工具简介 Tornado是嵌入式实时领域里最新一代的开发调试环境。Tornado给嵌入式系统开发人员提供了一个不受目标机资源限制的超级开发和调试环境。Tornado 包含三个高度集成的部分: ·运行在主机和目标机上的强有力的交叉开发工具和实用程序; ·运行在目标机上的高性能、可裁剪的实时操作系统VxWorks; ·连接主机和目标机的多种通讯方式,如:以太网,串口线,ICE或ROM 仿真器等。 对于不同的目标机,Tornado给开发者提供一个一致的图形接口和人机界面,如图1-1所示。 图1-1 当使用Tornado的开发人员转向新的目标机时,不必再花费时间学习或适应新的工具;对深嵌入式应用开发者来说更重要的是,Tornado所有的工具都是驻留在开发平台上的。在嵌入式系统工具发展历史上,Tornado是第一个实现了当目标机资源有限时开发工具仍可使用而且功能齐全的开发环境。另外,所有工具都通过一个中央服务器(Target Server)与目标机的通讯,因此无论连结方式是Ethernet,还是串口线、ICE仿真器、ROM仿真器或客户设计的调试通道,所有工具均可使用。 Tornado提供了一套完整的GNU Tool开发工具链,其中包括: ·CPP:C预处理

实例解析linux内核I2C体系结构(2)

实例解析linux内核I2C体系结构(2) 华清远见刘洪涛四、在内核里写i2c设备驱动的两种方式 前文介绍了利用/dev/i2c-0在应用层完成对i2c设备的操作,但很多时候我们还是习惯为i2c设备在内核层编写驱动程序。目前内核支持两种编写i2c驱动程序的方式。下面分别介绍这两种方式的实现。这里分别称这两种方式为“Adapter方式(LEGACY)”和“Probe方式(new style)”。 (1)Adapter方式(LEGACY) (下面的实例代码是在2.6.27内核的pca953x.c基础上修改的,原始代码采用的是本文将要讨论的第2种方式,即Probe方式) ●构建i2c_driver static struct i2c_driver pca953x_driver = { .driver = { .name= "pca953x", //名称 }, .id= ID_PCA9555,//id号 .attach_adapter= pca953x_attach_adapter, //调用适配器连接设备 .detach_client= pca953x_detach_client,//让设备脱离适配器 }; ●注册i2c_driver static int __init pca953x_init(void) { return i2c_add_driver(&pca953x_driver); } module_init(pca953x_init); ●attach_adapter动作 执行i2c_add_driver(&pca953x_driver)后会,如果内核中已经注册了i2c适配器,则顺序调用这些适配器来连接我们的i2c设备。此过程是通过调用i2c_driver中的attach_adapter方法完成的。具体实现形式如下: static int pca953x_attach_adapter(struct i2c_adapter *adapter) { return i2c_probe(adapter, &addr_data, pca953x_detect); /* adapter:适配器 addr_data:地址信息 pca953x_detect:探测到设备后调用的函数 */ } 地址信息addr_data是由下面代码指定的。 /* Addresses to scan */ static unsigned short normal_i2c[] = {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,I2C_CLIENT_END}; I2C_CLIENT_INSMOD;

Linux内核启动流程分析(一)

很久以前分析的,一直在电脑的一个角落,今天发现贴出来和大家分享下。由于是word直接粘过来的有点乱,敬请谅解! S3C2410 Linux 2.6.35.7启动分析(第一阶段) arm linux 内核生成过程 1. 依据arch/arm/kernel/vmlinux.lds 生成linux内核源码根目录下的vmlinux,这个vmlinux属于未压缩, 带调试信息、符号表的最初的内核,大小约23MB; 命令:arm-linux-gnu-ld -o vmlinux -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o init/built-in.o --start-group arch/arm/mach-s3c2410/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o drivers/built-in.o net/built-in.o --end-group .tmp_kallsyms2.o 2. 将上面的vmlinux去除调试信息、注释、符号表等内容,生成arch/arm/boot/Image,这是不带多余信息的linux内核,Image的大小约 3.2MB; 命令:arm-linux-gnu-objcopy -O binary -S vmlinux arch/arm/boot/Image 3.将 arch/arm/boot/Image 用gzip -9 压缩生成arch/arm/boot/compressed/piggy.gz大小约 1.5MB;命令:gzip -f -9 < arch/arm/boot/compressed/../Image > arch/arm/boot/compressed/piggy.gz 4. 编译arch/arm/boot/compressed/piggy.S 生成arch/arm/boot/compressed/piggy.o大小约1.5MB,这里实 际上是将piggy.gz通过piggy.S编译进piggy.o文件中。而piggy.S文件仅有6行,只是包含了文件piggy.gz; 命令:arm-linux-gnu-gcc -o arch/arm/boot/compressed/piggy.o arch/arm/boot/compressed/piggy.S 5. 依据arch/arm/boot/compressed/vmlinux.lds 将arch/arm/boot/compressed/目录下的文件head.o 、piggy.o 、misc.o链接生成arch/arm/boot/compressed/vmlinux,这个vmlinux是经过压缩且含有自解压代码的内核, 大小约1.5MB; 命 令:arm-linux-gnu-ld zreladdr=0x30008000 params_phys=0x30000100 -T arch/arm/boot/compressed/vmlinux.lds a rch/arm/boot/compressed/head.o arch/arm/boot/compressed/piggy.o arch/arm/boot/compressed/misc.o -o arch/arm /boot/compressed/vmlinux

Linux内核漏洞调试环境搭建

Linux内核漏洞调试环境搭建 一.前言 之前没怎么用过Linux,但是那天看到exploit-db上有不少Linux内核漏洞的POC。当时想如果可以请自动手调试一下这些漏洞,肯定会学到一些Linux下特定漏洞的利用技巧。(比如怎么利用空指针引用漏洞来进行本地提权)。所以就GOOGLE了很多关于Linux内核调试的文章,虽然一步一步老老实实照前人的指点的做,但是还是问题连着问题。反反复复的尝试,才历尽千心万苦搭建起了这个内核漏洞调试环境。 在此过程中得到了广大网友的帮助,特别是wzt85和塞(他的ID为塞)这两位前辈的指点。既然取之于“网”,那我觉得应该把这个过程用文字描述出来放到网络上,与同道中人分享。 本文的第二部分将简单介绍目前Linux下内核调试的几种常用调试技术路线,由于我对Linux的了解确实不多,所以这一部分写的肯定会很不专业,但目的在于抛砖引玉——更专业的文章烦请自行GOOGLE。 本文的第三部分会详细介绍该调试环境的搭建过程,关键点会有截图说明。 本文的第四部分是一点补充性的文字。 二.Linux下内核调试技术路线 1.QEMU+GDB QEMU是一款开源的虚拟机软件,它自身带有gdb stub可用于和Host 主机上的GDB通信来对Guest主机的Linux内核进行源码(C代码)级调试。为实现源码级调 试,那必须要有调试信息以及符号表,所以首先从https://www.sodocs.net/doc/9a10582552.html,上下载一份 Linux内核源代码进行编译。编译成功后会得到bzImage文件和vmlinux文件。其中vmlinux就是要供Host主机上的GDB进行调试的带有调试信息,符号表的内核文 件。 使用这种方法试验环境的搭建比较简单,而且最吸引人的地方在于它能够实现源码级的调试。但是遗憾的是,这种方法调试不了漏洞。因为当Guest主机上的内核发生内存访问异常的时候,Host主机中的GDB根本得不到异常事件,这样一来也就无法获知是那条指令引发的异常,以及被访问的内存地址是什么。

相关主题