没有mmu可以跑Linux吗?
内容提要
内存管理单元(MMU)是为了保证计算机系统的安全性而产生的,它可以让应用程序访问虚拟内存。在Linux中,MMU机制是必须的,但是运行没有MMU的Linux内核代码也是可能的,只需要进行适当的裁剪和配置。uClinux是针对没有MMU的处理器的嵌入式Linux操作系统,它没有虚拟内存和内存保护的功能。在uClinux中,进程之间共享运行空间,而且不能使用fork()函数。此外,uClinux使用的是扁平格式的可执行文件。在移植应用程序到uClinux时,需要注意一些特性,如将fork()改为vfork(),使用特定的编译选项等。
延伸解读
无MMU环境下的内存保护缺失与风险控制
uClinux没有内存保护,所有进程共享同一物理地址空间,一个无效指针就可能引发地址错误,导致程序崩溃甚至系统挂起。因此代码必须仔细编程并深入测试。不过,文章指出嵌入式uClinux程序通常在出厂前已固化,不存在外部程序侵入的隐患,只要经过较完整测试,出问题的概率可控制在有限范围内。
从fork到vfork:多任务编程模型的调整
uClinux没有fork()系统调用,因为无法完整复制进程且不支持copy-on-write。它提供vfork(),父进程调用后子进程共享全部内存空间(包括堆栈),子进程需通过exit()或exec()结束,再唤醒父进程。文章提醒,大量使用fork()的网络后台程序可能需要实质修改,甚至重写,才能适应这种共享地址空间的模型。
扁平格式与PIC:可执行文件的取舍
uClinux使用扁平格式而非ELF,扁平格式只包含代码、数据和重定位信息,非常紧凑。它支持位置无关代码(PIC)和固定基准地址加载两种模式:PIC运行快、代码紧凑,但有大小限制(如Motorola 68K的16位相对跳转限制程序不超过32KB);固定基准地址则无大小限制,但加载后系统开销较多。移植时需用-elf2flt转换,且不能strip或使用-O2优化,以免破坏FLAT文件。
Q&A
没有MMU的处理器能运行Linux吗?
可以,但需要对标准Linux内核进行裁剪和配置,使用针对无MMU处理器的嵌入式Linux版本,如uClinux。
uClinux和标准Linux主要有什么区别?
uClinux没有MMU,不支持虚拟内存和内存保护;不能运行时增加进程栈;不支持分页;可执行程序是flat格式而非ELF;不能用fork()而要用vfork();使用RAMDISK等。
为什么uClinux中不能使用fork()函数?
因为fork()需要MMU实现copy-on-write页面复制,而uClinux没有MMU,无法完整可靠地复制进程,所以用vfork()替代,子进程与父进程共享内存空间。
uClinux没有内存保护会带来什么风险?
无特权进程调用无效指针也会触发地址错误,可能导致程序崩溃甚至系统挂起。因此代码需仔细编程和测试。但嵌入式程序通常出厂前已固化,风险可控。
将应用程序移植到uClinux需要注意哪些关键点?
配置时选--disable-shared和--enable-static;将fork()改为vfork();在编译和链接选项中加入-Wl,-elf2flt以生成FLAT格式;转换时不能使用strip去除信息,避免使用-O2优化。
uClinux如何解决没有虚拟内存带来的内存分配问题?
uClinux支持位置无关代码(PIC)或固定基准地址加载程序;用预分配缓冲区池替代malloc()以减少碎片;用户空间程序使用mmap()分配内存,malloc()实质是mmap()的封装;限制可分配空间不大于RAM。