[转]不间断的运行

此文转自这里,是 Palm 界著名大神 UGlee 写的经典文章,为了防止这种神一样的文章以后不知道什么时候就找不到成为历史长河中的碎片(太夸张了……),我就转过来吧。如果你是学 Computer Science 的,而且没读过这篇文章,那么你……别告诉我你是学 Computer Science 的 -_-!

这个帖子是回答Gadgeteer和Yucc等朋友探讨Palm/PPC/实达8K的关于系统内存使用方面的问题。

首先我来说PPC和Palm的。PPC和PC在内存使用上如出一辙,是常规意义上的多任务系统,它具有内存管理单元,而且是硬件上的(CPU中),所以每个用户程序有自己独立的程序内存空间,静态数据内存空间,和栈空间。而动态内存的使用,也就是你在C语言中New一个对象,或者Malloc内存的时候,是使用系统所有程序共享的堆内存空间。

由于使用了内存管理单元,它有很好的进程保护特性,一个程序是不可能轻易更改其他程序的内存资料的,这也是安全性和系统稳定性的一个保证--不过稳定性更多的是从操作系统理论上讲的,其前提是无穷大的物理内存可用。。而非实时操作系统理论中并不涉及程序的响应时间问题,也不考虑物理内存紧张的时候系统性能恶化和程序无法申请内存时的应对--而这恰恰是很多嵌入式系统的real world环境,所以,在实际应用中这样延续桌面甚至服务器系统的设计方式是否符合用户的需求,就时一个大大的问号了。这也是PPC和Smartphone遇到的最尴尬的问题。

而Win32体系,由于从桌面上延伸过来,更多的考虑了程序或者程序开发的向前兼容问题,在内存管理上还有其他的弱点。典型的问题就是内存漏洞和内存泄漏。在Win32构架中,系统没办法Defrag内存碎片,即使还有相当多的内存可用,如果没有一段连续的空间,仍然无法申请到足够的内存;而从系统动态内存中申请到的内存,如果程序忘记归还,或者程序意外中止,都会造成内存泄漏,这也是我们在桌面上系统越用越慢,内存越用越少的主要原因。

另外的一个问题是,Win32体系,和所有其他的桌面操作系统一样,都是针对串行非挥发存储设计的(Win的前身DOS-Disk Operating System, , 虽然磁盘是一个界于串行存储和随机存储之间的物理设备,但是在数据结构的概念上它还是一个串行存储设备)。那么,程序在执行前需要从磁盘上载入,OS的进程列表中出现一个新的进程,分配栈空间和静态内存空间,然后程序运行,绝大多数程序都会用到动态内存。而打开文件的时候,多数情况下也需要先吧文件或者至少是文件中的一部分内容读入内存,转换成为程序需要的数据结构,在使用结束之后再重新串行化数据,写入文件。这个看起来很麻烦的方式,在磁盘操作系统上无可厚非,只能如此,谁让内存会掉电呢?

在PPC上,由于读卡的速度会成为很多程序的瓶颈,所以还做了一个特殊的设计,就是分配一段内存出来虚拟文件系统,就像我们在桌面上也有一些程序可以虚拟一个软驱一样。当然这和从扩展卡上读入数据相比还是快的,而且最基本的应用可以直接放入内存也很方便,但是从效率上,就相当滑稽了。程序本来需要的就是一个数据结构或者数据对象,而得到这个对象确要这样来作:把对象串行化一个可以顺序存取的对象,把它放在一段虚拟成FAT驱动器的内存中,每次使用不但要花费双倍的内存存放,还要经过一次读写和一次转换。那为什么不直接存储这个数据对象,原位使用呢?

这就是PalmOS的设计方式。

在操作系统教材中是没可能找到一个PalmOS这样的四不象怪物的。它有一个多任务的内核,但是确只能有一个用户程序在运行,有系统级的图形控件,在底层支持笔画输入而不是字符输入,只有几K的系统栈空间,动态内存空间更是少的可怜(最捍的Tungsten C是4M,Tungsten T是2M,而OS4/3.x设备最多不超过256K),在系统只有不足100K的内存可用的时候,仍然可以畅快的运行80%以上的程序。

PalmOS没有用户程序级的多进程/多线程支持--这是一个缺点,在流式数据应用的时候会有力不从心的感觉:表现在部分多媒体应用和网络应用上。不过当我们把注意力集中在一个程序的运行过程的时候,就会发现PalmOS设计上优秀的一面。

一个程序在多任务操作系统(PC或者PPC)中运行时需要这些内存:
1、OS进程列表中的一项,记录进程的所有寄存器状态和内存指针,其实也就是CPU现场,用于切换程序的时候保存和还原现场。这部分内存可以忽略不急。
2、程序的执行代码空间。
3、程序的静态数据空间,可大可小,但至少界面和全局变量是要初始化的吧。
4、栈空间,用户函数调用的时候传递参数。也是可大可小,不过面向对象编程的时候,难以控制函数调用的嵌套次数,甚至有些编程风格恶劣的程序员经常用它来传递大的数据对象,那栈空间可能就会很大很大了。
5、堆空间,也就是动态内存,从程序角度而言是存放临时对象的,不过这个临时经常会大的恐怖,比如处理图片的时候。

在PalmOS中,创造了一个独特的Storage Heap概念。通常我们就把他成为Palm上的文件系统,但是从程序角度而非用户角度而言,它和文件的差异就太大了。Storage Heap是使用类似数据库的方式存储的,它有安全读写检查,以此保证数据的安全性和完整性不被破坏;它可以直接的指针操作,具有和内存访问一样的效率。那么,文件(这是用户角度的名称)和数据对象(这是程序角度的名称)就完美的统一了。而当不在需要把文件转换成数据对象的时候,我们还需要那么大的堆空间干嘛呢? (流式应用除外,

而程序本身,也是放在Storage Heap里面的,执行的时候只要把CPU的代码段指针直接指想程序代码的入口即可,连程序代码也是不需要载入过程的。

PalmOS在系统底层的图形控件支持,大大减少了程序绘制界面需要的内存空间,所以绝大多数程序只要控制一下不太多的全局变量就可以了。几K的空间通常就是非常奢侈的了。

由于PalmOS只有一个用户程序可以运行,而系统的栈空间只给了2K,所以,程序员不得不用指针传递大数据对象,不但减少了内存需求,而且提高了效率。

在内存泄漏和内存碎片问题上,PalmOS也有优秀设计。后台的内存管理程序会在空闲时或者连续内存不足时整理内存碎片(需要程序开发者使用特定的API分配动态内存,不过Palm程序开发者都会这样做的),也可以回收程序忘记回收的动态内存。

通过这些方式,PalmOS把系统内存的使用降低到了少的可怜的程度,同时也把程序的运行效率推向了极致。

一些朋友曾经问过,在PalmOS6中会不会向DOS->Windows那样带来系统效率的大大降低,答案是:完全不会。如果你看懂了上面这些关于PalmOS内存使用的描述,你很容易明白该如何迁移PalmOS5->6,无非就是加入程序进程空间的保护,和使用私有的栈空间而已,这些和PalmOS的高效内存使用没有太大关系。PalmOS高效的精髓在于它的Storage Heap设计。我相信BEOS的开发者在OS6中会完全延续这一方式。

(要出去吃东西,待续...)

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.