本帖所述的操作系统源代码和《都江堰操作系统与嵌入式系统设计》一书,均可以在 www.djyos.com 中免费下载。
都江堰操作系统(简称djyos)是一个操作系统,但不是“又一个操作系统”,它是一个全新思路的操作系统。
djyos操作系统是以事件为核心进行调度的,这种调度策略使程序员可以按人类认知事物的习惯而不是计算机的习惯来编程。
普通操作系统中,调度是以线程为核心的,事件被作为线程的数据,标榜为“事件触发”的软件模型,也是由线程在一旁候着,待特定事件发生时线程恢复运行并把它作为输入数据加以处理。
以事件为核心的调度,则像设备和内存一样,把线程虚拟机作为处理事件所需要的资源看待,当某事件需要处理时,分配或者创建一个线程虚拟机给该事件,并启动该线程虚拟机处理事件。
djyos虽然刚出生,但已经不仅仅是一个内核了,是一个初具雏形的操作系统,目前包括以下模块:
抢占式多事件调度系统
内存管理模块
内存池管理模块
资源管理模块
中断管理模块
锁(含信号量和互斥量)模块,支持优先级继承
泛设备管理模块
文件系统模块
含擦除平衡的flash文件系统驱动模块
看门狗模块
约400页的说明文档,各模块详情请看此文档以及共享之代码
嵌入式操作系统的成功之道
随着嵌入式系统的日益复杂化,嵌入式现在系统越来越成为嵌入式产业的核心,君不见,而在我们国家,嵌入式操作系统几乎是个空白,2008年的十大嵌入式企业以及中国电子信息产业100强中,竟然没有一家是从事嵌入式操作系统的,就连有一个自主操作系统作为副业的都没有。这既是中国嵌入式行业的悲哀,也是对中国工程师的鞭策。
然而,实时嵌入式操作系统市场是如此成熟和完整,新操作系统如要从中分一杯羹,无异于在钢板上钉钉子。即使如此,仍然有不少人前仆后继地往里挤,在前人不断的“壮烈牺牲”中,我看到的是机会与挑战并存。嵌入式操作系统是一个细分市场,所以不会形成桌面系统寡头控制的局面,在桌面系统上,是windows和unix系操作系统双寡头局面,这种情况绝不会出现在嵌入式领域。这就给了后起之秀一个机会,只要你的产品好,工程师认同,你就有机会。嵌入式操作系统的目标用户是工程师,而工程师是一个善于学习的群体,容易接受新事物的群体,这也是djyos的机会。
都江堰操作系统就在这样的环境中,应运而生,我们有理由期待它能脱颖而出。分析一下那些壮烈了的操作系统,我们要吸取的教训很多:
1、没有创新就没有生存之本。看许多发布的操作系统,不外乎就是现有操作系统理论的简单复制,一上来就给人“又一个操作系统”的印象,根本吸引不了人们的眼球。而djyos则不一样,在构成嵌入式操作系统的几个重要方面:调度器、中断管理、设备管理、资源管理等方面,都又非常突出的创新,甚至是理论创新。尤其是在调度器方面,可以说是彻底革新。
2、要贴合用户需求,不能片面强调单项性能。看许多发布的操作系统,在宣传自己的优异性时,不外乎上下文切换时间多么短、占用系统资源多么少、功能模块多么多、线程间通信手段多么丰富。有或者说自己的C语言率多么高,移植需要修改的代码行多么少,等等!整个就是闭门造车,根本没有从用户的角度考虑,不知道代码工程师需要什么,也不知道系统工程师需要什么,更不知道产品经理和研发经理需要什么。djyos不同,他本来就是产品研发工程师写出来的操作系统,它充分考虑到用户的需求,他从技术角度,协助产品经理(研发经理)组织项目团队,协助系统工程师从软硬件联合设计的角度设计系统架构,协助代码工程师写出移植性和一致性都很高的代码。
3、要戒除IT界的浮躁,有许多操作系统发布时,还只是一个简单的内核,连基本的文档都没有,代码也是乱哄哄的没有注释。用户拿到手里,根本就云里雾里。要知道,你一个新生事物,用户是不会有耐心等你成熟的,即使你真的能够成熟,在你成熟的过程中,用户早已审美疲劳了。一个新生的操作系统,应该一上来就给人一种令人耳目一新的冲击,才能是用户有兴趣往下了解你。djyos系统在发布时,就已经是一个完整的操作系统,而不是一个简单的内核,而且带有408页的文档(还是有意压缩篇幅之后的),写这个文档花的时间,远比写一个内核要长,近2万行的代码,有约1/4是注释。
轮嵌入式操作系统的可移植性
许多操作系统夸耀自己的可移植性时,爱这样说:
“超过xx%代码由C语言编写,只有xx个函数是汇编,移植时只有xx个函数需要修改”。他们所关注的不外乎是操作系统本身从一个硬件平台移植到另一个硬件平台的难易度,这根本就是舍本逐末的提法。试问,一个含嵌入式系统的产品中,操作系统重要还是应用程序重要?我们说嵌入式操作系统是嵌入式产业的核心,是针对整个产业来说的,毕竟,操作系统的装机量远大于任何一个运行于操作系统的应用程序。而对具体产品来说,则应用程序无论从哪个方面讲都远比操作系统重要。对一个企业来说,尤其如此,企业可能有非常多的衍生产品,他们同同一份操作系统拷贝,或者有许多产品系列,系列之间的操作系统也只是稍有不同。他们花在移植操作系统上的时间,远小于应用程序的工作量,甚至可以忽略不计。因此,操作系统的可移植性,应该把重点放在协助应用程序移植上,那才是可移植性的精髓所在。
djyos在这方面是非常出色的,举个例子,如果某企业有两个相似产品,产品L不需要显示界面,产品H需要显示界面,其他功能相同,在的djyos下,你可以轻易做到:
1、把软件分成两大块,一块是显示部分代码,称为模块A,另一块是显示无关代码,显示无关代码完成产品的整体功能,调用显示部分的功能实现界面显示,称为模块B。
2、如果是si模式,A+B一起编译就是产品H,单独编译B就是产品L。编译产品L时连模块B中跟调用显示功能的代码都无需修改。
3、如果在dlsp模式下,则把模块A编译成A.out,模块B编译成B.out,把A.out和B.out一起copy到autorun目录下就成了产品H,单独copy B.out就成立产品L。
djyos的各模块设置,无不是围绕方便应用程序移植来设计,多事件调度器、泛设备组件、异步信号同步功能、事件和事件类型同步、应用程序模块加载器等,都为此做了许多考虑。今天很累了,暂不细说,在接下来的一段时间里,我将系列化发帖,讲述djyos中如何协助应用程序可移植,以及软件可移植性与可靠性之间的关系。
项目经理和系统工程师需要什么样的可移植性
许多人认为,可移植性就是软件从一个平台换到另一个硬件平台,仍然能正常运行的能力。这种说法是很笼统的,我们在细分一下,其中至少存在以下几个层面:
是否需要修改代码。
是否需要修改配置。
是否需要重新编译。
是否能够运行。
运行的结果是否正确。
听过有人说:C语言编写的代码,哪有移植性的问题。这种看法谬之大矣,等于说:我用拼音输入法写文章,所以我的文章是可移植的。关于C语言程序的可移植性,我的文档《都江堰操作系统与嵌入式产品设计》的第16章有详细的说明。用标准c语言写的程序,只能保证在支持标准C的编译环境中成功编译,不能确保能够正确运行。
比如下面这段代码,用指令实现10uS延时:
for(i=100; i>0; i--);
该语句无论在什么平台下,它都可以编译、运行,但结果可能不正确。具体延时量,与CPU的速度、编译器的效率、编译器的优化级别等都有关系,我们称之为”耦合“,在《都江堰操作系统与嵌入式产品设计》的第11章论述了什么是耦合以及如何解耦。含上述代码的软件,在移植时,必须修改代码。一种改进的方法是,把100定义为符号常量,如下:
#define cn_10us 100
for(i=cn_10us; i>0; i--);
这种方法只不过增加了代码的可读性,并降低了代码修改的工作量而已,本质上还是要修给代码并重新编译。djyos提供的改进方法是,有操作系统提供几个共享变量,他们是在操作系统初始化过程中被赋值的:
1. uint32_t u32g_ns_of_u32for;
当 delay_var是 32 位无符号整数时,每个循环消耗的纳秒数。
2. uint32_t u16g_ns_of_u32for;
当 delay_var是 16 位无符号整数时,每个循环消耗的纳秒数。
3. uint32_t u8g_ns_of_u32for;
当 delay_var是 8 位无符号整数时,每个循环消耗的纳秒数。
4. volatile uint32_t u32g_delay_10uS;
用 32 位无符号数做循环变量,延时 10uS 需要的循环次数。
在si模式下,若用下列语句做指令延时,可确保延时时间是100微秒。
volatile uint32_t delay_var;
for(delay_var =100000/u32g_ns_of_u32for; delay_var >0; delay_var --);
然而,这只是djyos解除软件与CPU运行速度之间耦合的一个小技巧而已,djyos更着重的是从系统架构入手,帮助项目经理和开发经理组织团队,帮助系统架构师理清组件之间数据流动和代码互动之间的关系。
现在的嵌入式产品开发,从一个新平台重新开始开发的机会相对会少一些。更常见的情况是,拿一套已经有了型的代码到处修改客户化做新项目,或者依据市场需求把产品改一改,添加一点新的需求,去掉一些老的功能,做系列化型号。广义地,就一个功能组件来说,它的运行环境整个由硬件、操作系统、以及应用项目的其他组件共同组成。应用项目某组件的变化,也是运行环境的变化,也可能需要移植,而且这种移植更加广泛,更加受项目经理的重视。djyos系统更加关注的是广义的移植,从这个角度,即使硬件和操作系统部分不改变,某组件的运行平台的数量,也跟使用该组件的衍生产品型号一样多。如果不注意广义平台的可移植性,一个组件往往会在这个型号中好使,那个型号中就不行了,按下葫芦浮起瓢,防不胜防,烦不胜烦!最后造成的是,实现相同功能的组件,在不同的衍生型号中就是不一样。日子久了,这样的东西就会充斥企业的产品中,并与企业历史相结合,企业历史留下来的人和流下来的势力格局有限制了改进问题的机会,许多企业里面软件版本繁多而且凌乱,难于管理,就是这样造成的。解决这个问题,需要一个优秀的系统设计师,在项目设计之初就确定一个良好的系统架构,djyos从技术角度上,对项目经理和系统工程师提供帮助,为新项目的开发和老项目的改造都提供支持。试举例如下:
某工程由多个团队协同开发,某中断的初始化以及ISR代码由团队B负责,另外一个组件由团队A开发,组件A有一个线程需要阻塞等待某中断发生。那么,在传统模式下,团队A和团队B之间在技术上,至少有一个信号量在联系,线程等待信号量而中断释放信号量。别看这个简单联系,它造成的后果就是两个模块互相关联(耦合),中断ISR中至少有一句是跟组件A相联系的,线程和ISR之间至少有一个共享变量——信号量句柄!ISR和线程之间至少失去了独立的命名空间,即使你不用共享变量,那么,ISR至少需要提供一个手段,使线程能够把信号量的地址告知。总之,两个团队之间不可能再是完全独立的关系。而使用djyos的异步信号同步技术,则团队A可以根本不知道团队B的存在。
多团队共同开发的项目中,项目经理最希望看到的是,两个团队之间各自完成自己的任务,各自的任务之间不互相依赖,这样两个团队之间的开发进度就可以异步安排。而如果两个组件之间有耦合的话(就像刚才的例子,通过信号量耦合),至少有一些团队协调工作要做。而djyos中,两个团队是完全独立工作的,独立开发、独立编译、独立加载运行。
|