uclinux与linux的不同

来源:互联网 发布:sql注入漏洞如何修复 编辑:程序博客网 时间:2024/06/06 12:42

题外话:感觉通过比较uclinux与linux的不同,能让我更加深入地理解linux的虚拟内存机制,体会实时内核跟分时内核的不同,有无MMU的不同,以及它给应用程序编程带来的极大的便利。

可执行程序的加载

  在普通的Linux中,虚拟内存技术的使用使我们不必关心一个应用程序是从什么地址开始的。
          即使所有的应用程序都使用同一个连接脚本配置。
      也就是说,即使它们使用的虚拟地址是重叠的,经过页表和页目录的转换之后它们也可以被映射到不同的物理地址。
      但是在uClinux中,由于缺少了MMU的硬件支持,在内核中不会发生地址的映射转换,这样就必须解决应用程序的加载问题。
      uClinux系统使用flat可执行文件格式,gcc的编译器不能直接形成这种文件格式,
     但是可以首先编译生成coff可执行格式或者elf可执行格式的文件,
      然后使用格式转化工具(coff2flt或者elf2flt)将这些中间代码转换成flat文件格式。
    当用户执行一个flat格式的可执行程序时,uclinux内核的执行文件加载器将对flat文件进行进一步处理,主要是对reloc段进行修正。
    下面对do_load_flat_binary()函数的分析将详细描述其实现过程。

用户程序的内存分配
1.堆
           标准Linux上用户程序的动态内存分配是通过调用glibc库的malloc函数从程序的堆空间中获得内存页面。
            在虚拟内存系统中malloc是使用sbrk调用将程序的数据段向后扩展得到。
            应用程序的内存使用分布图如图8-2所示。
      而在uClinux的平地址模式中,堆空间是通过mmap调用获得的。
          uClibc中的malloc函数是一个非常简单的实现,它将所有分配内存的细节都交给了内核。


  uClinux中的栈紧随着用户程序的数据段,而堆是从栈底向下扩张的,如图8-2所示。
          由于uClinux中没有内存保护机制,这样必须在程序编译连接的时候就确保为栈保留了足够的空间使它不会覆盖程序的数据段和代码段。

FLAT可执行文件格式
为了适应uClinux中新的内存管理模式而引入了一种专为它所使用的flat可执行文件格式。
          可执行文件头是前面描述的reloc段,紧接着是程序的文本段、数据段、未初始化数据段。
          可执行文件加载到内存之后程序的堆栈段紧随在BSS段的后面。
flat可执行文件格式如图8-2所示。
          但是注意在可执行文件被加载到内存的时候reloc段仍然在外存中。

Uclinux为了实现在kernel运行中,动态在外存中加载应用程序(这一点ut-kernel是没有的,ut-kernel是不是不能做人机交互界面的?一旦动态运行程序的话,肯定需要MMU虚拟内存的,就算不需要,也要找像uclinux这样也可以动态加载app的,还有感想,在最下面),引入了一种新的文件格式:FLAT可执行文件格式,uclinux里面不能用动态库(没MMU),所以被加载的应用程序都是静态编译连接的。所以应用程序的core_dump就不能用了(为什么回去查下)。
具有这种全新文件格式的文件被uclinux动态加载到内存中时,还要求uclinux自身具有识别该文件格式的代码块(通常是该文件格式自身的操作管理函数)。
还有FLAT格式的文件最前面有个relloc段,为什么必须有这个段呢。
下面我的一点理解:

因为当一个二进制文件被连接器连接完后,假设他的一函数符号的地址也被连接器固定了。因为正常的linux带MMU的,这个地址都是虚拟地址,后期可以动态地映射到不同的物理地址处。但是uclinux下就不行了,没了MMU,该地址一旦被连接器定下来,也就将成为实际运行的物理地址了。
但是连接器不可能自身给该文件一个死的物理地址,并且连接器自身也不知道该文件要被加载到什么实际地方。所以连接器只给一个相对应段基地址的偏移量。将这个偏移量放到统一的relloc段中。于是这个段就这样产生了。
等到实际加载该程序时,将实际的段基地址和偏移量一加就得到实际的该符号的物理地址了。

下面我的一点理解:
Ut-kernel和uclinux比较
感觉像ut-kernel,uc/os这种很简单的内核,里面就没什么好的框架,以及为以后可扩展性,中间件移植做考虑的东西。里面就纯粹是一任务调度算法加一些信号量,timer,锁,内存块管理之类的小东西。
但是如果以后要要在上面移植一些小规模的中间件,做些复杂的扩展,比如想让它有脚本的概念,支持脚本的运行。这些简单的RTOS就要被重新大搞了,依据现在的简单框架,把那些中间件都加上去肯定会把原来kernel架构搞的特别乱的。
不过ut-kernel当初设计也就是为了实现什么智能插座,用在汽车家电,空调,数码相机里面的。这些领域都要对ut-kernel再做个专门的处理,本身具体的应用程序也不复杂也不多。也就是ut-kernel用在专业性比较强的领域,这些领域不需要一个什么稍微比较通用的操作系统或者内核的支撑。就是简单地控制些任务的执行。
但是消费电子类产品就不一样了,如果选用不带MMU的内核。那么消费电子类那么多的丰富应用程序,ut-kernel是支撑不了的。


原创粉丝点击