uclinux和linux的区别

来源:
导读 大家好,我是本期栏目编辑小友,现在为大家讲解uclinux和linux的区别问题。 Linux操作系统 Linux是一个类似Unix的操作系统,可以自由使用

大家好,我是本期栏目编辑小友,现在为大家讲解uclinux和linux的区别问题。

Linux操作系统

Linux是一个类似Unix的操作系统,可以自由使用和传播。它是一个基于POSIX和UNIX的多用户、多任务、多线程、多CPU的操作系统。它可以运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了以网络为核心的Unix的设计思想,是一个性能稳定的多用户网络操作系统。

Linux操作系统诞生于1991年10月5日(这是第一次正式宣布)。Linux有许多不同的版本,但它们都使用Linux内核。Linux可以安装在各种计算机硬件设备中,如手机、平板电脑、路由器、视频游戏机、台式电脑、大型机和超级计算机。严格来说,

Linux这个词本身只是指Linux内核,但实际上,人们已经习惯了用Linux来描述基于Linux内核的整个操作系统,并使用GNU项目的各种工具和数据库。

uclinux

Uclinux代表微控linux,即“微控制器领域的linux系统”,是Lineo公司的主打产品,也是开源嵌入式Linux的典范。UCLinux主要是为目标处理器没有MMU(内存管理单元)的嵌入式系统设计的。已经成功移植到很多平台。因为没有MMU,它的多任务实现需要一些技巧。

Linux是一种流行的操作系统,它与UNIX系统兼容,并且具有开放源代码。最初设计为桌面系统,现在广泛应用于服务器领域。更大的影响是逐渐应用于嵌入式设备。UClinux就是在这种氛围下诞生的。在英文单词uClinux中,u表示Micro、small,c表示Control,所以uClinux就是Micro-Control-linux,字面意思是“为微控制领域设计的Linux系统”。

UClinux是嵌入式linux的一个非常重要的分支,已经成功应用于路由器、机顶盒、PDA等领域。它在内存管理上与标准的Linux有本质的区别。

uclinux和linux的区别。

对于uCLinux来说,它是为没有MMU的处理器设计的,所以不能使用处理器的虚拟内存管理技术。UCLinux仍然使用内存分页管理,系统启动时会对实际内存进行分页。加载应用程序时,程序被分页。但由于没有MMU管理,uCLinux实际上采用的是实内存管理策略。UCLinux系统直接访问内存,所有程序中访问的地址都是实际的物理地址。操作系统不保护内存空间,每个进程实际上共享一个运行空间。在一个进程执行之前,系统必须为该进程分配足够的连续地址空间,然后将它们全部装入主存的连续空间。

没有Memory ProtecTIon的操作会导致这样的结果:即使一个无效指针被非特权进程调用,也会触发地址错误,有可能导致程序崩溃甚至系统挂起。显然,在这样的系统上运行的代码必须经过仔细的编程和彻底的测试,以确保健壮性和安全性。

由内核加载的进程必须能够独立运行,而不管它们在内存中的位置如何。实现这一目标的第一种方法是一旦程序被加载到内存中,就“固定”它的引用地址。另一种方法是生成只使用相对寻址的代码(称为“位置无关代码”,简称PIC)。UClinux支持这两种模式。

ELF可以生成一个特殊的代码——位置无关代码(PIC)。用户使用gcc的-fPIC指令GNU编译系统生成PIC代码。它是实现共享库或共享可执行代码的基础。这段代码的特殊性在于,它可以加载到内存地址空间的任何地址中执行。这就是为什么加载程序可以在过程中动态链接共享库。

PIC的实现利用了这样一个事实,即代码段中的任何指令和数据段中的任何变量之间的距离是一个常数,与代码段和数据段的绝对存储位置无关。因此,编译器在数据段的开头创建一个表,称为全局偏移量表。得到.GOT包含该目标模块引用的每个全局数据目标的条目。编译器还为GOT中的每个条目生成一个重定位记录。加载时,动态链接器将重新定位GOT中的每个条目,以便它包含正确的绝对地址。PIC代码通过代码中的GOT间接引用每个全局变量,使得代码中简单的数据引用变得复杂,必须添加获取GOT适当入口内容的指令。对只读数据的引用也是基于同样的原理,所以加IC编译的代码比一般代码要贵。

频繁的内存分配将导致内存碎片,并可能耗尽系统资源。对于那些使用动态内存分配的应用程序,增强健壮性的一种方法是用预分配缓冲池替换malloc()调用。因为uclinux中没有使用虚拟内存,所以没有实现进出内存的页面交换,因为不能保证页面会被加载到RAM中相同的位置。

UClinux目标板处理器缺少用于内存管理的硬件单元,使得linux的系统接口需要改变。也许最大的区别是没有fork()和brk()系统调用。调用fork()复制进程以创建子进程。

在Linux下,fork()是使用copy-on-write页面来实现的。由于没有MMU,uclinux不能完整、可靠地复制一个进程,也没有对copy-on-write的存取。为了弥补这一缺陷,uClinux实现了vfork(),当父进程调用vfork()来创建子进程时,两个进程共享它们的全部内存空间,包括堆栈。子进程要么代替父进程执行(此时父进程已经sleep)直到子进程调用exiTI()退出,要么调用exec()执行一个新的进程,这个时候将产生可执行文件的加载。即使这个进程只是父进程的拷贝,这个过程也不能避免。当子进程执行exit()或exec()后,子进程使用wakeup把父进程唤醒,父进程继续往下执行。

  uClinux 既没有自动生长的堆栈,也没有brk()函数,这样,用户空间的程序必须使用mmap() 命令来分配内存。为了方便,在uclinux的C语言库中所实现的malloc()实质上就是一个mmap()。在编译时,可以指定程序的堆栈大小。

  总结:在应用程序移植到uClinux,以及自己写代码的过程中,我们将始终围绕这几个特性来做:

  1, 在configure时,如果可能则需要在configure时,选上—disable-shared和—enable-static.

  2, 将源代码中所有出现的fork()改成vfork();

  3, 在Makefile中的交叉编译器和编译选项,链接选项里加上-Wl,-elf2flt。尽管这只是一个链接选项,但我还是小心地在LDFLAGS和CFLAGS,甚至在CC中指定了该选项。

  改选项是将ELF格式转换成uClinux所能识别的FLAT格式。在做这个转换过程,我们是不能对ELF文件使用strip去除一些信息,更有甚者不能使用-O2 选项来优化代码。因为去掉的某些信息可能导致最终生成的FLAT格式文件运行出现问题。

标签:

版权声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢您的支持与理解。