论文部分内容阅读
摘 要: 随着嵌入式技术的不断发展,将开源的Linux操作系统和嵌入式技术结合起来,无疑具有广泛的应用前景。从嵌入式Linux系统开发中的实时性问题和裁剪技术问题入手,对嵌入式Linux系统的关键技术进行研究,并提出对应的改进方案。
关键词: 嵌入式;Linux;函数裁剪;实时性
中图分类号:TP3 文献标识码:A 文章编号:1671-7597(2013)0110102-01
1 嵌入式技术的发展及现状
嵌入式技术诞生以来,随着控制芯片的微型化和操作系统功能的加强,嵌入式系统开始应用于各个领域;Linux操作系统以其开放的源代码、高效的内核以及丰富的应用软件而在嵌入式领域有独特的表现,因此嵌入式Linux已经成为嵌入式领域的主流。
嵌入式技术的发展主要经历了以下三个阶段[1]:(1)可编程控制器。以单芯片为核心,没有操作系统,大多应用于专业性极强的工控领域;优点是价格低、使用简单;缺点是功能单一、效率低下。(2)以嵌入式CPU为基础的嵌入式系统。具有简单的操作系统。克服了可编程控制器的效率低下问题,具有一定的兼容性;缺点是通用性较差,且用户界面不友好;主要用于程序运行监控及系统负载控制。(3)嵌入式操作系统。此类嵌入式系统可以运行在不同类型的微处理器上,内核效率高、兼容性好,支持多任务管理,具备网络和图形用户界面支持。
市面上已经有多种嵌入式实时Linux操作系统,典型的有RT-Linux、RED-Linux以及KURT等。RT-Linux开发的核心思想是“架空”Linux内核,从而可以尽快执行其他的实时进程,修改Linux内核源码后,将Linux内核及系统本身任务的优先级设为最低,同时将实时任务的优先级设置为最高,这样实时任务的模块就可以在需要时加载到系统内核中,所以可以认为RT-Linux是可抢占内核的。与RT-Linux的可抢占内核方式不同,RED-Linux可以直接修改系统内核源码,并将其中较长的例程分解成细粒度的代码段,这样实现了在代码中插入抢占点的功能,用以抢占内核。RED-Linux的内核抢占延迟较小,能够适用不同复杂程度嵌入式系统的要求。
虽然嵌入式Linux有何很多优势,但也有需要改进之处。本文接下来主要从Linux内核改造及实时性两个方面对嵌入式Linux操作系统进行研究。
2 嵌入式Linux的内核裁剪技术
很多人认为Linux系统太大,不适合用作嵌入式系统,这是因为Linux系统安装了很多非必须的应用,如KDE、Apache等。为使Linux系统满足嵌入式操作系统的需求,可以根据需求进行内核裁剪,以满足实际应用。目前常用的内核裁剪技术有四种[2]:删除冗余文件、共享库裁剪、修改内核源码以及相同功能软件包替换。
Linux内核的动态库中保存了可复用的预先编译的代码。应用程序可以静态链接或动态链接的方式调用这些库。静态链接是从动态库中复制需要的代码到可执行文件中;动态链接在可执行文件运行时才加载动态库。共享库与可执行文件中都存在一些导入/导出符号表,导出符号是在可执行文件中定义但可被其他文件使用的符号,导入符号是被可执行文件调用的符号。共享库被链接前都会检查导入符号相关的代码在内存中是否存在。在进行内核裁剪的时候,可以将永远不会被其他文件调用的导出符号删除。基于上述原理,裁剪技术的过程可以描述为:查找共享库中会被其他程序/共享库调用的导出符号;将提供以上导出符号的目标文件链接为较小的共享库;重复上面两步直到不能继续裁剪为止。
目前的共享库裁剪技术的粒度只是精确到目标文件级别,在保留的目标文件内部不可避免的存在一些不必要的导出符号。为提高内核裁剪的粒度,本文提出一种函数级的裁剪技术,以进一步裁剪目标文件中的冗余代码。将共享库的代码按照源码组成的方式划分成函数块,并且建立这些函数块和导出符号的关系。遍历每个节点,如果函数块a调用函数块b,就称a依赖于b,a直接或间接调用的函数块都不能从动态库中删除,将所有不能被删除的函数块做上标记。经过递归标记后,函数块N1、N3以及N6都可以从动态库中删除。
要真正实现函数级内核裁剪,有两个必须首先解决的问题[3]:(1)如何根据导入/导出符号确定某一库函数调用的支持函数?(2)如何确定不同函数块间的依赖关系?为解决这两个问题,可以从链接器链接库函数的过程入手。链接器链接库函数时可能会直接从外部的目标文件引入一个符号,所以我们可以分析ELF符号表中被引用的库函数的信息,从而找到引用的库函数或支持函数。另外由于库函数间可能存在间接的引用,因此首先需要找到库函数的被引用函数,再找到这些函数引用的函数,如此递归直到所有的函数都被显示定义为止。
Linux中动态库的源码是用C语言写的,所以难以划分函数块,因为反汇编代码和源码中的函数一般是对应的,所以可以用反汇编工具将共享库的代码段反汇编,然后再进行函数块的划分。反汇编后的代码函数块开始于,其中symbol是函数块的名称,结束于ret指令,如下所示:
:0055FBA1 F7D8
:0055FBA3 F7D8 neg eax
:0055FBA7 880A mov byte ptr [edx], cl
:0055FBAB 03C6 add eax, esi
:0055FBAD 5E pop esi
:0055FBAE C3 ret
3 嵌入式Linux中的实时性
嵌入式Linux系统实时性的关键是在一定时间内完成预定义的操作。按照时限对系统的影响程度,可以将实时系统分为软实时和硬实时系统。软实时系统可以容忍偶尔超过时限的操作,硬实时系统对超时限的操作是零容忍的。不管是哪类的实时系统,都可以用响应时间、生存时间以及吞吐量来衡量系统的实时性。响应时间是嵌入式Linux系统从识别外部事件到做出响应的时间;生存时间是请求数据的有效等待时间,一旦超过这个时间,数据将不再有效;吞吐量是单位时间内系统能够处理的总事件。 当前硬实时性的实现方法主要有“修改内核为实时内核”和“采用双内核”两种。前者改写内核中的进程调度、内存管理以及中断处理策略,并用改写后的调度器替换内核原有的进程调度器,这一方法要求开发人员精通Linux内核,开发难度较大。双内核机制在操作系统的最底层添加一层实时核心层,这样在一个硬件平台上就有两个互相配合的系统内核,其中一个管理实时的多任务,另外一个管理非实时任务。
嵌入式Linux实时系统要求能够实时调度任务,调度多进程时要不断切换进程,以使CPU得到最大的利用率。嵌入式Linux的实时调度算法主要有离线算法和在线算法两种,前者预先分配每个任务的调度次序和切换时间,后者动态调度进程任务。静态优先级调度算法的典型代表是速率单调调度算法(Rate Monotonic,RM),动态优先级调度算法的典型代表是最早期限优先调度算法(Early Deadline First,EDF)。RM调度任务的依据是任务的周期,它事先为每个进程分配一个优先级,每次调度任务时选择优先级最高的任务,必要时可以剥夺当前进程的CPU时间片。EDF按照任务的最终响应期限调度任务,任务的期限越早说明越紧急,所以被赋予较高的优先级,从而得到优先调度。
EDF和RM两种调度策略都是基于任务优先级的,而且他们定义优先级的方法不同,两种方法同时实现的策略可以通过“任务调度策略标识位”和“可加载模块”实现。设置任务优先级时,先判断当前任务队列中的调度算法种类,并设置标志位,然后将运行队列中使用这两种调度策略的进程数目初始化为0。当有新的进程任务加入时,将其使用的调度策略数目的标志位加1。如此以来用户将感觉不到两种调度策略的冲突。可加载模块的方式也是设置两个标志位,但处理方式和前一种方式不同;可加载模块的方式在使用某种策略调度模块时,先监测另外一种调度方式是否已经加载,如果另外一种调度策略已经加载了此模块,则因为两种调度策略不能共存的原因,就不能够使用当前的调度策略加载模块。嵌入式Linux系统的定时器芯片会产生周期性中断,每隔一定时间中断CPU,并检查是否需要调度任务。当前的嵌入式Linux系统的时间片粒度比较粗,为细化时间片粒度,可以增加定时芯片的中断频率。每次定时器芯片产生中断时,内核都会从用户空间返回,并检查定时器链表,避免了多次中断的延迟问题,提高了实时性。
4 总结
本文对嵌入式Linux系统中的内核裁剪、实时化改造等关键技术进行了研究,并将原有的文件级内核裁剪改进为函数级内核裁剪,提高了系统的实时化水平。
参考文献:
[1]钟忻,嵌入式Linux系统开发中的关键技术的研究与实现[D].国防科技大学,2008.
[2]黄义文,Linux操作系统内核裁剪的分析[D].中国民航飞行学院学报,2010(5).
[3]蒋习旺,嵌入式Linux的实时性研究与改进[J].哈尔滨工程大学,2009.
关键词: 嵌入式;Linux;函数裁剪;实时性
中图分类号:TP3 文献标识码:A 文章编号:1671-7597(2013)0110102-01
1 嵌入式技术的发展及现状
嵌入式技术诞生以来,随着控制芯片的微型化和操作系统功能的加强,嵌入式系统开始应用于各个领域;Linux操作系统以其开放的源代码、高效的内核以及丰富的应用软件而在嵌入式领域有独特的表现,因此嵌入式Linux已经成为嵌入式领域的主流。
嵌入式技术的发展主要经历了以下三个阶段[1]:(1)可编程控制器。以单芯片为核心,没有操作系统,大多应用于专业性极强的工控领域;优点是价格低、使用简单;缺点是功能单一、效率低下。(2)以嵌入式CPU为基础的嵌入式系统。具有简单的操作系统。克服了可编程控制器的效率低下问题,具有一定的兼容性;缺点是通用性较差,且用户界面不友好;主要用于程序运行监控及系统负载控制。(3)嵌入式操作系统。此类嵌入式系统可以运行在不同类型的微处理器上,内核效率高、兼容性好,支持多任务管理,具备网络和图形用户界面支持。
市面上已经有多种嵌入式实时Linux操作系统,典型的有RT-Linux、RED-Linux以及KURT等。RT-Linux开发的核心思想是“架空”Linux内核,从而可以尽快执行其他的实时进程,修改Linux内核源码后,将Linux内核及系统本身任务的优先级设为最低,同时将实时任务的优先级设置为最高,这样实时任务的模块就可以在需要时加载到系统内核中,所以可以认为RT-Linux是可抢占内核的。与RT-Linux的可抢占内核方式不同,RED-Linux可以直接修改系统内核源码,并将其中较长的例程分解成细粒度的代码段,这样实现了在代码中插入抢占点的功能,用以抢占内核。RED-Linux的内核抢占延迟较小,能够适用不同复杂程度嵌入式系统的要求。
虽然嵌入式Linux有何很多优势,但也有需要改进之处。本文接下来主要从Linux内核改造及实时性两个方面对嵌入式Linux操作系统进行研究。
2 嵌入式Linux的内核裁剪技术
很多人认为Linux系统太大,不适合用作嵌入式系统,这是因为Linux系统安装了很多非必须的应用,如KDE、Apache等。为使Linux系统满足嵌入式操作系统的需求,可以根据需求进行内核裁剪,以满足实际应用。目前常用的内核裁剪技术有四种[2]:删除冗余文件、共享库裁剪、修改内核源码以及相同功能软件包替换。
Linux内核的动态库中保存了可复用的预先编译的代码。应用程序可以静态链接或动态链接的方式调用这些库。静态链接是从动态库中复制需要的代码到可执行文件中;动态链接在可执行文件运行时才加载动态库。共享库与可执行文件中都存在一些导入/导出符号表,导出符号是在可执行文件中定义但可被其他文件使用的符号,导入符号是被可执行文件调用的符号。共享库被链接前都会检查导入符号相关的代码在内存中是否存在。在进行内核裁剪的时候,可以将永远不会被其他文件调用的导出符号删除。基于上述原理,裁剪技术的过程可以描述为:查找共享库中会被其他程序/共享库调用的导出符号;将提供以上导出符号的目标文件链接为较小的共享库;重复上面两步直到不能继续裁剪为止。
目前的共享库裁剪技术的粒度只是精确到目标文件级别,在保留的目标文件内部不可避免的存在一些不必要的导出符号。为提高内核裁剪的粒度,本文提出一种函数级的裁剪技术,以进一步裁剪目标文件中的冗余代码。将共享库的代码按照源码组成的方式划分成函数块,并且建立这些函数块和导出符号的关系。遍历每个节点,如果函数块a调用函数块b,就称a依赖于b,a直接或间接调用的函数块都不能从动态库中删除,将所有不能被删除的函数块做上标记。经过递归标记后,函数块N1、N3以及N6都可以从动态库中删除。
要真正实现函数级内核裁剪,有两个必须首先解决的问题[3]:(1)如何根据导入/导出符号确定某一库函数调用的支持函数?(2)如何确定不同函数块间的依赖关系?为解决这两个问题,可以从链接器链接库函数的过程入手。链接器链接库函数时可能会直接从外部的目标文件引入一个符号,所以我们可以分析ELF符号表中被引用的库函数的信息,从而找到引用的库函数或支持函数。另外由于库函数间可能存在间接的引用,因此首先需要找到库函数的被引用函数,再找到这些函数引用的函数,如此递归直到所有的函数都被显示定义为止。
Linux中动态库的源码是用C语言写的,所以难以划分函数块,因为反汇编代码和源码中的函数一般是对应的,所以可以用反汇编工具将共享库的代码段反汇编,然后再进行函数块的划分。反汇编后的代码函数块开始于
:0055FBA1 F7D8
:0055FBA3 F7D8 neg eax
:0055FBA7 880A mov byte ptr [edx], cl
:0055FBAB 03C6 add eax, esi
:0055FBAD 5E pop esi
:0055FBAE C3 ret
3 嵌入式Linux中的实时性
嵌入式Linux系统实时性的关键是在一定时间内完成预定义的操作。按照时限对系统的影响程度,可以将实时系统分为软实时和硬实时系统。软实时系统可以容忍偶尔超过时限的操作,硬实时系统对超时限的操作是零容忍的。不管是哪类的实时系统,都可以用响应时间、生存时间以及吞吐量来衡量系统的实时性。响应时间是嵌入式Linux系统从识别外部事件到做出响应的时间;生存时间是请求数据的有效等待时间,一旦超过这个时间,数据将不再有效;吞吐量是单位时间内系统能够处理的总事件。 当前硬实时性的实现方法主要有“修改内核为实时内核”和“采用双内核”两种。前者改写内核中的进程调度、内存管理以及中断处理策略,并用改写后的调度器替换内核原有的进程调度器,这一方法要求开发人员精通Linux内核,开发难度较大。双内核机制在操作系统的最底层添加一层实时核心层,这样在一个硬件平台上就有两个互相配合的系统内核,其中一个管理实时的多任务,另外一个管理非实时任务。
嵌入式Linux实时系统要求能够实时调度任务,调度多进程时要不断切换进程,以使CPU得到最大的利用率。嵌入式Linux的实时调度算法主要有离线算法和在线算法两种,前者预先分配每个任务的调度次序和切换时间,后者动态调度进程任务。静态优先级调度算法的典型代表是速率单调调度算法(Rate Monotonic,RM),动态优先级调度算法的典型代表是最早期限优先调度算法(Early Deadline First,EDF)。RM调度任务的依据是任务的周期,它事先为每个进程分配一个优先级,每次调度任务时选择优先级最高的任务,必要时可以剥夺当前进程的CPU时间片。EDF按照任务的最终响应期限调度任务,任务的期限越早说明越紧急,所以被赋予较高的优先级,从而得到优先调度。
EDF和RM两种调度策略都是基于任务优先级的,而且他们定义优先级的方法不同,两种方法同时实现的策略可以通过“任务调度策略标识位”和“可加载模块”实现。设置任务优先级时,先判断当前任务队列中的调度算法种类,并设置标志位,然后将运行队列中使用这两种调度策略的进程数目初始化为0。当有新的进程任务加入时,将其使用的调度策略数目的标志位加1。如此以来用户将感觉不到两种调度策略的冲突。可加载模块的方式也是设置两个标志位,但处理方式和前一种方式不同;可加载模块的方式在使用某种策略调度模块时,先监测另外一种调度方式是否已经加载,如果另外一种调度策略已经加载了此模块,则因为两种调度策略不能共存的原因,就不能够使用当前的调度策略加载模块。嵌入式Linux系统的定时器芯片会产生周期性中断,每隔一定时间中断CPU,并检查是否需要调度任务。当前的嵌入式Linux系统的时间片粒度比较粗,为细化时间片粒度,可以增加定时芯片的中断频率。每次定时器芯片产生中断时,内核都会从用户空间返回,并检查定时器链表,避免了多次中断的延迟问题,提高了实时性。
4 总结
本文对嵌入式Linux系统中的内核裁剪、实时化改造等关键技术进行了研究,并将原有的文件级内核裁剪改进为函数级内核裁剪,提高了系统的实时化水平。
参考文献:
[1]钟忻,嵌入式Linux系统开发中的关键技术的研究与实现[D].国防科技大学,2008.
[2]黄义文,Linux操作系统内核裁剪的分析[D].中国民航飞行学院学报,2010(5).
[3]蒋习旺,嵌入式Linux的实时性研究与改进[J].哈尔滨工程大学,2009.