uClinux体系阐发
发布日期:2011-05-18
Linux是一种很受欢迎的利用体系,它与UNIX体系兼容,开放源代码。它原来被筹划为桌面体系,如今广泛应用于办事器范畴。而更大的影响在于它正垂垂的应用于嵌入式配置。uClinux正是在这种氛围下孕育孕育产生的。在uClinux这个英文单词中u表现Micro,小的意思,C表现Control,控制的意思,以是uClinux便是Micro-Control-Linux,字面上的明白便是"针对微控制范畴而筹划的Linux体系"。
uClinux小型化的做法
标准Linux大概采取的小型化要领
1. 重新编译内核
Linux内核采取模块化的筹划,即很多结果块可以独立的加上或卸下,开辟职员在筹划内核时把这些内核模块作为可选的选项,可以在编译体系内核时指定。因此一种较通用的做法是对Linux内核重新编译,在编译时过细的选择嵌入式配置所须要的结果支持模块,同时删除不须要的结果。通过对内核的重新配置,可以使体系运行所须要的内核明显减小,从而缩减资源利用量。
2. 制作root文件体系映象
Linux体系在启动时必须加载根(root)文件体系,因此剪裁体系同时包括root file system的剪裁。在x86体系下,Linux可以在Dos下,利用Loadlin文件加载启动。
uClinux采取的小型化要领
1.uClinux的内核加载要领
uClinux的内核有两种可选的运行要领:可以在flash上直接运行,也可以加载到内存中运行。这种做法可以淘汰内存须要。
Flash运行要领:把内核的可实行映象烧写到flash上,体系启动时从flash的某个地点开始逐句实行。这种要领实际上是很多嵌入式体系采取的要领。
内核加载要领:把内核的压缩文件存放在flash上,体系启动时读取压缩文件在内存里解压,然后开始实行,这种要领相对巨大一些,但是运行速率大概更快(ram的存取速率要比flash高)。同时这也是标准Linux体系采取的启动要领。
2.uClinux的根(root)文件体系
uClinux体系采取romfs文件体系,这种文件体系相敷衍一样通常的ext2文件体系恳求更少的空间。空间的节流来自于两个方面,起首内核支持romfs文件体系比支持ext2文件体系须要更少的代码,其次romfs文件体系相对大抵,在创建文件体系超等块(superblock)须要更少的存储空间。Romfs文件体系不支持动态擦写生存,敷衍体系须要动态生存的数据采取假造ram盘的要领举行处理惩罚处罚(ram盘将采取ext2文件体系)。
3.uClinux的应用步调库
uClinux小型化的另一个做法是重写了应用步调库,相敷衍越来越大且越来越全的glibc库,uClibc对libc做了精简。
uClinux对用户步调采取静态连接的情势,这种做法会使应用步调变大,但是基于内存办理的标题,不得不如许做(这将在下文对uClinux内存办理展开阐发时举行阐发),同时这种做法也更靠近于通常嵌入式体系的做法。
uClinux的开辟环境
GNU开辟套件
Gnu开辟套件作为通用的Linux开放套件,包括一系列的开辟调试东西。紧张组件:
Gcc: 编译器,可以做成交错编译的情势,即在宿主机上开辟编译目标上可运行的二进制文件。
Binutils:一些资助东西,包括objdump(可以反编译二进制文件),as(汇编编译器),ld(连接器)等等。
Gdb:调试器,可利用多种交错调试要领,gdb-bdm(背景调试东西),gdbserver(利用以太网络调试)。
uClinux的打印终端
通常环境下,uClinux的默认终端是串口,内核在启动时全部的信息都打印到串口终端(利用printk函数打印),同时也可以通过串口终端与体系交互。
uClinux在启动时启动了telnetd(长途登录办事),利用者可以长途登录上体系,从而控制体系的运行。至于是否容许长途登录可以通过烧写romfs文件体系时有效户决定是否启动长途登录办事。
交错编译调试东西
支持一种新的处理惩罚处罚器,必须具备一些编译,汇编东西,利用这些东西可以形成可运行于这种处理惩罚处罚器的二进制文件。敷衍内核利用的编译东西同应用步调利用的有所差别。在表明差别点之前,须要对gcc连接做一些阐发:
.ld(link description)文件:ld文件是指出连接时内存映象格局的文件。
crt0.S:应用步调编译连接时须要的启动文件,紧张是初始化应用步调栈。
pic:position independence code ,与位置无关的二进制格局文件,在步调段中必须包括reloc段,从而使的代码加载时可以举行重新定位。
内核编译连接时,利用ucsimm.ld文件,形成可实行文件映象,所形成的代码段既可以利用间接寻址要领(纵然用reloc段举行寻址),也可以利用绝对寻址要领。如许可以给编译器更多的优化空间。由于内核大概利用绝对寻址,以是内核加载到的内存地点空间必须与ld文件中给定的内存空间完全雷同。
应用步调的连接与内核连接要领差别。应用步调由内核加载(可实行文件加载器将在反面讨论),由于应用步调的ld文件给出的内存空间与应用步调实际被加载的内存位置大概差别,如许在应用步调加载的进程中须要一个重新职位地方的进程,即对reloc段举行修正,使得步调举行间接寻址时不至于堕落。(这个标题在i386等高级处理惩罚处罚器上要领有所差别,本文将在反面进一步阐发)。
由上述讨论,至少须要两套编译连接东西。在讨论过uClinux的内存办理后本文将给出整个别系的变乱流程以及体系在flash和ram中的空间散布。
可实行文件格局
先对一些名词作一些阐发:
coff(common object file format):一种通用的东西文件格局
elf(excutive linked file):一种为Linux体系所采取的通用文件格局,支持动态连接
flat:elf格局有很大的文件头,flat文件对文件头和一些段信息做了简化
uClinux体系利用flat可实行文件格局,gcc的编译器不克不及直接形成这种文件格局,但是可以形成coff或elf格局的可实行文件,这两种文件须要coff2flt或elf2flt东西举行格局转化,形成flat文件。
当用户实行一个应用时,内核的实行文件加载器将对flat文件举行进一步处理惩罚处罚,紧张是对reloc段举行修正(可实行文件加载器的详见fs/binfmt_flat.c)。以下对reloc段进一步讨论。
须要reloc段的源头头底子因是,步调在连接时连接器所假定的步调运行空间与实际步调加载到的内存空间差别。倘如有如许一条指令:
jsr app_start;
这一条指令采取直接寻址,跳转到app_start地点处实行,连接步调将在编译完成是谋略出app_start的实际地点(设若实际地点为0x10000),这个实际地点是根据ld文件谋略出来(由于连接器假定该步调将被加载到由ld文件指明的内存空间)。但实际上由于内存分派的干系,利用体系在加载时无法包管步调将按ld文件加载。这时要是步调仍旧跳转到绝对地点0x10000处实行,通常环境这是非法的。一个办理步调是增长一个存储空间,用于存储app_start的实际地点,设若利用变量addr表现这个存储空间。则以上这句步调将改为:
movl addr, a0;
jsr (a0);
增长的变量addr将在数据段中占用一个4字节的空间,连接器将app_start的绝对地点存储到该变量。在可实行文件加载时,可实行文件加载器根据步调将要加载的内存空间谋略出app_start在内存中的实际位置,写入addr变量。体系在实际处理惩罚处罚是不须要知道这个变量的确切存储位置(也不大概知道),体系只要对整个reloc段举行处理惩罚处罚就可以了(reloc段有标识,体系可以读出来)。处理惩罚处罚很大抵只须要对reloc段中存储的值同一加上一个偏置(要是加载的空间比预想的要靠前,实际上是减去一个偏移量)。偏置由实际的物理地点肇始值同ld文件指定的地点肇始值相减谋略出。
这种reloc的要领部分是由uClinux的内存分派标题引起的,这一点将在uClinux内存办理阐发时阐发。
针对及时性的办理方案
uClinux本身并没有存眷及时标题,它并不是为了Linux的及时性而提出的。别的有一种Linux--Rt-linux存眷及时标题。Rt-linux实行办理器把平常Linux的内核当成一个任务运行,同时还办理了及时进程。而非及时进程则交给平常Linux内核处理惩罚处罚。这种要领已经应用于很多的利用体系用于加强利用体系的及时性,包括一些商用版UNIX体系,Windows NT等等。这种要领长处之一是实现大抵,且及时性能容易查验。长处之二是由于非及时进程运行于标准Linux体系,同别的Linux商用版本之间保持了很大的兼容性。长处之三是可以支持硬及时时钟的应用。uClinux可以利用Rt-linux的patch,从而加强uClinux的及时性,使得uClinux可以应用于财产控制、进程控制等一些及时恳求较高的应用。
uClinux的内存办理
应该说uClinux同标准Linux的最大区别就在于内存办理,同时也由于uClinux的内存办理引发了一些标准Linux所不会出现的标题。本文将把uClinux内存办理同标准Linux的那内存办理部分举行比较阐发。
标准Linux利用的假造存储器技能
标准Linux利用假造存储器技能,这种技能用于提供比谋略机体系中实际利用的物理内存大得多的内存空间。利用者将以为到宛如步调可以利用非常大的内存空间,从而使得编程职员在写步调时不消思量谋略机中的物理内存的实际容量。
为了支持假造存储办理器的办理,Linux体系采取分页(paging)的要领来加载进程。所谓分页既是把实际的存储器支解为雷同大小的段,比喻每个段1024个字节,如许1024个字节大小的段便称为一个页面(page)。
假造存储器由存储器办理机制及一个大容量的快速硬盘存储器支持。它的实现基于局部性原理,当一个步调在运行之前,没有须要全部装入内存,而是仅将那些当前要运行的那些部分页面或段装入内存运行(copy-on-write),别的临时留在硬盘上步调运行时要是它所要访问的页(段)已存在,则步调连续运行,要是发明不存在的页(段),利用体系将孕育孕育产生一个页错误(page fault),这个错误导致利用体系把须要运行的部分加载到内存中。须要时利用体系还可以把不须要的内存页(段)互换到磁盘上。利用如许的要领办理存储器,便可把一个进程所须要用到的存储器以化整为零的要领,视需求分批加载,而内核步调则允从属于每个页面的页码来完成寻址各个存储器区段的变乱。
标准Linux是针对有内存办理单位的处理惩罚处罚器筹划的。在这种处理惩罚处罚器上,假造地点被送到内存办理单位(MMU),把假造地点映射为物理地点。
通过付与每个任务差别的假造--物理地点转换映射,支持差别任务之间的掩护。地点转换函数在每一个任务中定义,在一个任务中的假造地点空间映射到物理内存的一个部分,而另一个任务的假造地点空间映射到物理存储器中的别的地区。谋略机的存储办理单位(MMU)一样通常有一组寄存器来标识当前运行的进程的转换表。在当进步程将CPU放弃给另一个进程时(一次上下文切换),内核通过指向新进程地点转换表的指针加载这些寄存器。MMU寄存器是有特权的,只能在内核态才华访问。这就包管了一个进程只能访问本身用户空间内的地点,而不会访问和修改别的进程的空间。当可实行文件被加载时,加载器根据缺省的ld文件,把步调加载到假造内存的一个空间,由于这个缘故因由实际上很多步调的假造地点空间是雷同的,但是由于转换函数差别,以是实际所处的内存地区也差别。而敷衍多进程办应当处理惩罚处罚器举行进程切换并实行一个新任务时,一个告急部分便是为新任务切换任务转换表。我们可以看到Linux体系的内存办理至少实现了以下结果:
运行比内存还要大的步调。抱负环境下应该可以运行恣意大小的步调
◇可以运行只加载了部分的步调,紧缩了步调启动的时间
◇可以使多个步调同时驻留在内存中进步CPU的利用率
◇可以运行重定位步调。即步调可以方于内存中的恣意一处,并且可以在实行进程中移动。
◇写呆板无关的代码。步调不必事先约定呆板的配置环境。
◇减轻步调员分派和办理内存资源的包袱。
◇可以举行共享--比喻,要是两个进程运行同一个步调,它们应该可以共享步调代码的同一个副本。
◇提供内存掩护,进程不克不及以非授官僚领访问或修改页面,内核掩护单个进程的数据和代码以保卫别的进程修改它们。不然,用户步调大概会偶然偶尔偶然偶尔(或恶意)的粉碎内核或别的用户步调。
虚存体系并不是没有代价的。内存办理须要地点转换表和其他一些数据布局,留给步调的内存淘汰了。地点转换增长了每一条指令的实行时间,而敷衍有分外内存利用的指令会更告急。当进程访问不在内存的页面时,体系孕育产生失效。体系处理惩罚处罚该失效,并将页面加载到内存中,这须要极耗时间的磁盘I/O利用。总之内存办理活动占用了相称一部分cpu时间(在较忙的体系中约莫占10%)。
uClinux针对NOMMU的分外处理惩罚处罚
敷衍uClinux来说,其筹划针对没有MMU的处理惩罚处罚器,即uClinux不克不及利用处理惩罚处罚器的假造内存办理技能(应该说这种不带有MMU的处理惩罚处罚器在嵌入式配置中相称普偏)。uClinux仍旧采取存储器的分页办理,体系在启动时把实际存储器举行分页。在加载应用步调时步调分页加载。但是由于没有MMU办理,以是实际上uClinux采取实存储器办理战略(real memeory management)。这一点影响了体系变乱的很多方面。
uClinux体系敷衍内存的访问是直接的,(它对地点的访问不须要颠末MMU,而是直接送到地点线上输出),全部步调中访问的地点都是实际的物理地点。利用体系对内存空间没有掩护(这实际上是很多嵌入式体系的特点),各个进程实际上共享一个运行空间(没有独立的地点转换表)。
一个进程在实行前,体系必须为进程分派富裕的连续地点空间,然后全部加载主存储器的连续空间中。与之相映射的是标准Linux体系在分派内存时没有须要包管实际物理存储空间是连续的,而只要包管虚存地点空间连续就可以了。别的一个方面步调加载地点与预期(ld文件中指出的)通常都不雷同,如许relocation进程便是必须的。别的磁盘互换空间也是无法利用的,体系实行时要是缺少内存将无法通过磁盘互换来得到改造。
uClinux对内存的办理淘汰同时就给开辟职员提出了更高的恳求。要是从易用性这一点来说,uClinux的内存办理是一种倒退,退回了到了UNIX早期或是Dos体系时期。开辟职员不得不参加体系的内存办理。从编译内核开始,开辟职员必须报告体系这块开辟板到底拥有多少的内存(倘若你诱骗了体系,那将在反面运行步调时受到处罚),从而体系将在启动的初始化阶段对内存举行分页,并且标记已利用的和未利用的内存。体系将在运行应用时利用这些分页内存。
由于应用步调加载时必须分派连续的地点空间,而针对差别硬件平台的可一次成块(连续地点)分派内存大小限定是差别(如今针对ez328处理惩罚处罚器的uClinux是128k,而针对coldfire处理惩罚处罚器的体系内存则无此限定),以是开辟职员在开辟应用步调时必须思量内存的分派环境并存眷应用步调须要运行空间的大小。别的由于采取实存储器办理战略,用户步调同内核以及别的用户步调在一个地点空间,步调开辟时要包管不陵犯别的步调的地点空间,以使得步调不至于粉碎体系的正常变乱,或导致别的步调的运行非常。
从内存的访问角度来看,开辟职员的权利增大了(开辟职员在编程时可以访问恣意的地点空间),但与此同时体系的沉寂性也大为降落。别的,体系对多进程的办理将有很大的变革,这一点将在uClinux的多进程办理中阐发。
固然uClinux的内存办理与标准Linux体系相比结果相差很多,但应该说这是嵌入式配置的选择。在嵌入式配置中,由于资源等敏感因素的影响,普偏的采取不带有MMU的处理惩罚处罚器,这决定了体系没有富裕的硬件支持实现假造存储办理技能。从嵌入式配置实现的结果来看,嵌入式配置通常在某一特定的环境下运行,只要实现特定的结果,其结果相对大抵,内存办理的恳求完全可以由开辟职员思量。
标准Linux体系的进程、线程
进程:进程是一个运行步调并为其提供实行环境的实体,它包括一个地点空间和至少一个控制点,进程在这个地点空间上实行单一指令序列。进程地点空间包括可以访问或引用的内存单位的聚集,进程控制点通过一个一样通常称为步调计数器(program counter,PC)的硬件寄存器控制和跟踪进程指令序列。
fork:由于进程为实行步调的环境,因此在实行步调前必须先创建这个能"跑"步调的环境。Linux体系提供体系调用拷贝现行进程的内容,以孕育孕育产生新的进程,调用fork的进程称为父进程;而所孕育孕育产生的新进程则称为子进程。子进程会承继父进程的齐备特性,但是它有本身的数据段,也便是说,只管子进程变革了所属的变量,却不会影响到父进程的变量值。
父进程和子进程共享一个步调段,但是各自拥有本身的堆栈、数据段、用户空间以及进程控制块。换言之,两个进程实行的步调代码是一样的,但是各有各的步调计数器与本身的私流派据。
当内核收到fork恳求时,它会先稽核三件事:起首查抄存储器是不是富裕;其次是进程表是否仍有空缺;着末则是看看用户是否创建了太多的子进程。要是上报告三个条件餍足,那么利用体系会给子进程一个进程辨认码,并且设置cpu时间,接着设置与父进程共享的段,同时将父进程的inode拷贝一份给子进程运用,终极子进程会返回数值0以表现它是子进程,至于父进程,它大概等待子进程的实行结束,或与子进程各做个的。
exec体系调用:该体系调用提供一个进程去实行另一个进程的本领,exec体系调用是采取包围旧有进程存储器内容的要领,以是原来步调的堆栈、数据段与步调段都市被修改,只有效户区维持稳固。
vfork体系调用:由于在利用fork时,内核会将父进程拷贝一份给子进程,但是如许的做法相称浪费时间,由于大多数的环境都是步调在调用fork后就立即调用exec,如许刚拷贝来的进程地区又立即被新的数据包围失。因此Linux体系提供一个别系调用vfork,vfork假定体系在调用完成vfork后会顿时实行exec,因此vfork不拷贝父进程的页面,只是初始化私有的数据布局与准备富裕的分页表。如许现着实vfork调用完成后父子进程原形上共享同一块存储器(在子进程调用exec或是exit之前),因此子进程可以变动父进程的数据及堆栈信息,因此vfork体系调用完成后,父进程进入就寝,直到子进程实行exec。当子进程实行exec时,由于exec要利用被实行步调的数据,代码包围子进程的存储地区,如许将孕育孕育产生写掩护错误(do_wp_page)(这个时间子进程写的实际上是父进程的存储地区),
这个错误导致内核为子进程重新分派存储空间。当子进程正确开始实行后,将唤醒父进程,使得父进程连续以后实行。
uClinux的多进程处理惩罚处罚
uClinux没有mmu办理存储器,在实现多个进程时(fork调用天生子进程)须要实现数据掩护。
uClinux的fork和vfork:uClinux的fork便是vfork。实际上uClinux的多进程办理通过vfork来实现。这意味着uClinux体系fork调用完程后,要么子进程代替父进程实行(此时父进程已经sleep)直到子进程调用exit退出,要么调用exec实行一个新的进程,这个时间将孕育孕育产生可实行文件的加载,纵然这个进程只是父进程的拷贝,这个进程也不克不及克制。当子进程实行exit或exec后,子进程利用wakeup把父进程唤醒,父进程连续往下实行。
uClinux的这种多进程实现机制同它的内存办理精密干系。uClinux针对nommu处理惩罚处罚器开辟,以是被迫利用一种flat要领的内存办理模式,启动新的应用步调时体系必须为应用步调分派存储空间,并立即把应用步调加载到内存。缺少了MMU的内存重映射机制,uClinux必须在可实行文件加载阶段对可实行文件reloc处理惩罚处罚,使得步调实行时可以大概直接利用物理内存。