
都江堰操作系统,简称djyos,得名于一个伟快社操搞普斤大的水利工程:都江堰来自。
与传统操作系统不同,djyos不是以线程而是以事件为调冲度核心,这种调度算法使程序员摆脱模拟计算机执行过程编写程序的思维方式,而是按人类认知世360百科界的方式编写答境值明应用程序,就如同在嵌入式编程中殖乙杂临意创树心理引入了VC似的。djyos的调逐见叶她宽威度算法使程序员可以摆脱线程和进程的束缚,djyos没有有关线程的api,一个完全不懂线程知识的程序员也可以顺利地在djyos下编写应用程序。
- 中文名称 都江堰操作系统
- 外文名称 djyos
- 调度核心 事件
- 特点 实时内存管理
产品特点
挥春握护确蒸己尽待 djyos是一个全新来自的操作系统,它与现有的任何操作系统都没有亲缘关系,在构成操作系统的几个重要方面:调度器、中断管理、设备360百科管理、资源管理等方面,都又非常突出的创新,甚至是理论创新。通过这些创新,djyos能为应用程序设计者提供非常突出的特点:
(1)在调度器方面,可以说是举彻底革新,它几乎颠覆了传统的软件设计模式。对嵌入式编程来说,几乎是革命性的进步,它以事件为核心的调度方式病历化培易宣转预况,改变了过去操作系统要求程序员模拟计算机的思维方式的编程模式,使之可以按人类的思维方式编写应用程序;它使程序员可以摆脱线程和进程的束缚,djyos没有跟线程相关的API。特别是在嵌入式领域的程序员,有许多是行业背景很深的专家,但往往缺乏计算机操作系统方面的知识,他们是属输毛在djyos下编程,则可以无需开学习晦涩难懂的线程知识。
(2)天然匹配多核和分布式计算,djyos的调度算法是以事件为核心的,应用程序只管为事件编制处理程序,而线程和CPU核则被当做处理事件必须的资扬轴我适京源,由操作系统分配给事件,这种算法天生使多核编程使车把般官察干青阶更加简单,多核利用背初味率更高。众多周知,目前CPU正往多核化发地本下干亲都审刚展,嵌入式CPU甚至DSP也是如此,比如ADI公司的blackfin561就是一颗只有几十KB内存的双核DSP,djyos有计划移植到blackfin561上,有望成为第一个在只有几十KB内度拉段发营存的CPU上实现对双核的完美支持的RTOS。
(3)创新的加载方式和中断管理处选采场模块,可以实现比所有操作系统都快的中断响应太速度,并且在CPU启动后数十uS以内,应用程序的关键部分就可以实现对目标系统的控制,在操作系统加载过程中,就可以响应应用程序的中断ISR。
(4)实时的内存管理,八那格失少情在操作系统组件中,通常认为malloc函数是非实时组件,因为即使有充足的内存,malloc函数的执行时间也不可预计,不符合实时系统要求执行时间和结果均可预计的原则。但是djyos的内存管理,只要在系统设计时配备充足的内存,酸malloc的执行时间是快速而且可以预计的,而在只运行一个应用程序的实时系统中,内存不枯竭是容易做到的。
汽使怕短我(5)为项目经理和系杀动统工程师量身定制的系统架构,为工程师量身定制的API设置,特别利于系统工程师划分项目模块,利于项目经理组建和管理团队,利于工程师编写利于维护的解值代码。
设计理念
1.编院少美积奏执非苦九九加一原则与中断控制器
让软件设计中的99%工作更加简单易行,从而降低应用程序设计的综合复杂性和难度,对仅有的1%的极端需求更多地考虑可实现性而不是便利性,使应用程序能够实现这些极端功能,又不为了这极少数工作的方便性而使整个系统过于复杂,这个特点在djyos的中断管理中体现得淋漓尽致。
普通的操作系统,只是提供了几个函数,方便程序员编写ISR函数以及开关中断等。而djyos则不同,它把中断看做是一种特殊的事件,把它纳入事件管理的轨道。实际应用中,既有像键盘这样对实时性没有要求的中断,也有对中断响应延时时间非常苛刻的高速信号。
普通操作系统对这两种中断信号不加区分,把所有中断都看做需要快速响应的信号。它为没有实时要求的信号提供快速响应,而不能进一步改善高速信号的响应时间。而djyos却区别对待,它把中断分为实时中断和异步信号,任意一个中断源都可以设定自己属于实时中断还是异步信号。只要你把某中断设为实时中断,它将获得比传统操作系统快得多的响应延时,且在操作系统运行中,永远不会关闭实时中断使能,代价是,实时中断的ISR不能使用所有的操作系统API。而异步信号则响应时间比普通操作系统慢一些,但几乎所有事件服务可以使用的操作系统服务,它都可以使用,比如异步信号ISR允许使用malloc函数,编程上比普通操作系统ISR方便得多。异步信号的第二种响应方式则完全在事件上下文中,比异步信号ISR响应更加慢,但却获得了与主程序相同的操作系统服务。
所以说,在djyos下编程,对于绝大多数实时性要求不是那么高的中断,提供比传统操作系统方便得多的编程环境,而对极少数对响应时间非常苛刻的中断,则提供了比传统操作系统更高的实现的可能性。
2.事件调度,让工程师解放思想硬件和操作系统是舞台,程序员是演员,而项目经理、系统工程师则是导演、编剧。舞台可能是木板、沙石、水泥建造的,而软件开发平台则由硬件、操作系统管理下的线程等组成,就像演员不需要知道舞台是什么材料制造的,只需要用心演绎剧本一样,我们不应该要求程序员了解CPU内部运作过程以及线程和进程这些晦涩难懂的机制,只需要把软件功能实现就可以了。
在传统操作系统中,线程的创建、启动、暂停、停止、删除等无一不是由程序员自己控制的,在桌面系统(包括嵌入式的Windows CE)上,有Visual C++等工具替你包装,简化了多线程编程,在嵌入式环境中,程序员需要熟悉线程的一切。更重要的是,由多线程实现应用程序,是CPU执行过程决定的,要求程序员熟练操作线程,实际上就是要求程序员按照CPU执行过程思考问题。
djyos是按事件调度的,它使程序员可以按照人类认知事物的方式编写程序,没有任何跟线程相关的API函数,程序员只需要做以下两件事
(1)登记事件类型把需要计算机做的事情告诉告诉操作系统。
(2)2、编写事件处理函数。
我们知道,软件是用于解决实际问题的,这些问题可能需要很深的行业背景,比如化工、生物科学等,程序员则很可能是这些行业的专家,这些专家对计算机有可能一知半解,在嵌入式领域尤甚。要他们理解并熟练应用线程知识,需要花费很大的代价,以及很多的培训经费,而djyos下编程,他们就可以摆脱这些束缚,可以尽情地发挥自己的专业知识。
3.小goto与大GOTO写过C代码的都知道,goto是很受忌讳的语句,甚至有人根本不用。我们对函数内的goto耿耿于怀的同时,却无视长期存在的、组件之间、线程之间的大GOTO,甚至有些操作系统还为提供了丰富的大GOTO为卖点,说什么为应用程序提供丰富的服务。
什么是大GOTO呢?我们看看唤醒休眠中的线程函数的执行结果,假设这个函数的函数名是task_resume,并且假设该该操作系统是按优先级调度的。线程A调用task_resume(taskB_id)后,如果线程B的优先级高于A,则立即切换到B的上下文继续执行。所以,对线程A来说,相当于执行了一个跨组件的GOTO,对于线程B来说,它睡得好好的,却被人无缘无故地叫醒。对项目经理来说,即团队A与团队B之间存在直接的交叉控制,或称交叉跳转。
djyos不提供任何类似的操作,所有事件都是自己控制自己的行为,没有任何事件处理函数间交叉控制的可能,djyos认为,事件处理过程中,不会无缘无故地停止,也不会无缘无故地继续,djyos提供各种服务,让应用程序自己控制自己的行为。程序停下来,必定有其理由,要么是要等待一定的时间,djyos提供闹钟同步功能;要么是等待某个锁可用,djyos提供锁同步功能;要么是等待某事件结束,djyos提供事件同步功能……,总之,这些同步功能的支持下,应用程序每个事件都达到自己控制自己行为的目标,而彻底摒弃了应用程序模块之间的交叉控制。也就是说,djyos中不存在跨事件(对应其他操作系统的线程)的大GOTO。
4.友好组划分,帮助项目经理组建和管理团队一个大中型项目,需要划分为多个团队共同开发,项目经理梦寐以求的是,各个团队之间减少扯皮;项目进入联调阶段后,项目经理梦寐以求的是,各组件独立调通后就能协同运行,减少联调扯皮时间。即使一个人的项目,也会划分为多个组件,上述问题同样存在,而且,项目完成后,进入维护期后,组件独立性强的能大大降低维护工作量。
在由多个子团队协同开发的项目中,项目经理以及系统工程师必须考虑的问题是,哪些模块放在一起编译,哪些模块共享命名空间,如果在支持多进程的环境下开发,则还要考虑哪些模块在相同的地址空间运行。这些问题集中到一起,就是如何划分"软件友好组"的问题。在《都江堰操作系统与嵌入式系统设计》一书的第3章,用了相当长的篇幅用于讲述友好组。
友好组的定义很简单,就是可信赖的程序组成一个友好组,什么是可信赖的程序?同一个团队开发的程序是可信赖的。"友好"有两层意思,一是这些代码是为一个共同的目标,密切协作地完成任务;二是这些代码不会主动地、恶意地互相干扰和破坏,也不会故意执行非法操作。有两个特例是,如果同一个团队开发的两个模块将来可能会分成两个团队开发,应该将他们分成两个友好组;第二个特例是,两个模块的可靠性等级相差比较大,也应该分属两个友好组,这样,两个模块就可以使用不同强度的测试手段。
以设计软件的人为核心,是都江堰操作系统的核心思想之一。现代软件开发中,非常强调工程化开发的思想,在工程化开发中,任何软件策略都不能不考虑人的因素。划分友好程序和可疑程序是 djyos 操作系统设计中的一个根本性的策略,划分的依据是开发团队,而不是以技术特征,是都江堰操作系统当然的选择。把协同工作的团队开发的所有代码称作友好程序,划入一个友好组,而把所有不协同工作的团队以及个人开发的程序当成可疑程序,主要考虑的是人的因素。根据这个原则,操作系统自身的所有代码是由一个核心团队开发的,当然地成为一个友好代码组,操作系统开发团队无需与开发应用程序的团队和个人协作,它把所有应用程序都当作可疑程序;同样,一个应用程序是由一个人或者一个密切协作的团队开发的,该程序的所有代码形成一个友好组,而把所有其他应用程序以及操作系统都视为可疑程序。这与传统的观念不同,传统的观念认为,操作系统是可信程序,而用户程序是非可信程序。
djyos建立篱笆墙隔离友好组,使之不能互相影响和互相破坏,以及提供不同友好组之内完整的命名空间。根据硬件支持情况,友好组之间的保护分为两个级别。
(1)如果硬件支持,不同友好组拥有独立的寻址空间,他们之间的代码、数据在物理上互不可见,也就无法互相破坏。
(2)如果硬件不支持,在平板内存模式下实现逻辑隔离,在编写软件时,同一个友好组的代码独立编译,拥有独立的命名空间,友好组之间的函数、变量互不可见,使其不能显式地互相破坏。
5.轻耦合,实现组建独立开发和调试一个系统的各个模块,将不可避免地发生相互联系和相互影响,我们称之为模块间耦合。耦合分为良性耦合和恶性耦合,比如模块间互相传递必要的数据就是良性耦合,而模块间互相使用对方的数据,或者要求对方必须如何如何做,从而使模块间互相依赖,这种耦合叫做恶性耦合,下文中说到的耦合如不说明均指恶性耦合。系统模块级设计的目的就是使各模块间尽可能地互相独立,尽量减少彼此之间的耦合,即使不可避免耦合,也要仔细设计模块间的接口,使之成为良性耦合。这样,各模块就能够独立开发、独立维护、独立生存,能够通过动态裁剪来适应新的需求,使企业能够制定灵活的产品战略,当经营环境发生变化时,能够降低转型的成本。我们知道,耦合是造成团队间不能独立开发、项目开发中互相扯皮的罪魁祸首,且在联调时,模块间耦合越紧密,联调的工作量就越大。djyos致力于从技术的角度,帮助程序设计者降低甚至消除模块间的耦合,为此,djyos做了许多工作,这里略举一例。
我们知道,在操作系统支持下编程,线程执行过程中调用系统服务函数是最常见不过的动作了。这里隐藏着一个问题,系统服务函数会使用当前线程的栈,如果你没有为这些调用准备足够的栈空间,就可能因此造成栈溢出,产生不可预知的故障,这就是操作系统团队编写的代码与应用程序团队编写的线程代码发生了恶性耦合。每个线程在创建时,都会给它指定一个合适大小的栈,在台式机中,一般会在M级以上,这种耦合一般不会出问题,而在嵌入式系统中,由于内存稀缺,栈可能只有几十k。栈尺寸既要能满足线程需求,又不能占用太多的内存,这就要求能够准确估计线程所需的栈尺寸。然而,程序员只能准确估计自己写的代码所需要的栈尺寸,调用系统服务时,系统服务函数需要多少栈呢?应用程序的程序员是很难估算出来的。djyos对这种情况做了处理,他明确告诉程序员,你只需要估计自己写的代码需要的栈,并且详细说明了如何估计栈需求,系统在创建线程时,会自动加上系统服务所需要的栈,这样就避免了系统服务使用线程栈带来的问题。
6.天生匹配多核系统传统的操作系统,线程是调度的目标,而事件是作为被线程处理的数据(资源)而存在的,djyos以事件为调度目标,而把CPU以及线程当资源,这种倒过来的配置方法,天生就更加适合多核,我们有望在只有几十K大小的操作系统上,实现对称多核CPU的完美支持。以后的嵌入式芯片也会往多核方向发展,比如现在ADI公司的blackfin就有对称双核型号,而且blackfin是没有mmu的、典型的嵌入式CPU,其直接竞争对手--Ti也有类似的双核产品。
传统的操作系统下,由应用程序建立线程或进程,并为线程和进程编写代码,线程一般被绑定在某一个内核上,绑定方法有两种,一是由操作系统调配,另一种是由程序员指定,比如ADI的VDK操作系统,就是在编译阶段由程序员指定的。线程与CPU核的绑定,实际上就是应用程序代码与CPU核绑定。一个线程处理相应的计算任务,在传统模式下,即使某线程的计算任务频繁发生,也只能由该线程所在的CPU核上一一处理,你可以做一个实验,在双核机上,用Word把一个大型文件转换成PDF,在转换过程中,如果你没有运行其他程序,CPU占有率会一直在51%左右,就是说,一个CPU核一直忙,另一个则一直闲着。
djyos的事件调度,应用程序只管为事件编制处理程序,而线程是由操作系统分配的,线程绑定在哪个CPU核上,也是由操作系统决定的,这样就解除了应用程序代码与CPU核的绑定。如果某一类事件频繁发生,操作系统将会给它分配多个线程,这些线程将根据各CPU核的繁忙程度,分配到不同的CPU上。
7.拿来拿去主义计算机技术发展到现在,已经有很多技术积累,开发一个复杂的嵌入式产品,要懂得"拿来主义",不要完全从0开发全部软件和硬件。但是,怎样拿来呢?开发高可靠的产品,对使用外来代码会非常谨慎,甚至只使用有商业支持的外来代码。任何外来代码,都要经过通读、仔细分析,完全测试过以后才允许使用,有商业支持的代码,供应商会提供支持,这个过程进行得就快些;而没有商业支持的所谓开源代码,这些代码甚至没有完整的注释,读懂这样的代码,所花费的时间甚至不会比自己开发少多少。所以,高可靠产品的"拿来主义",主要靠继承企业自身积累的软件模块,来降低开发工作量。要使新产品开发时有东西可以拿来用,企业产品开发过程只就要非常注重"可拿去性",一句话,不拿去,何以拿来,而可拿去性,实质上就是可移植性!djyos系统支持下,在系统设计时强调"可拿来性",即系统融合现成的软件模块的能力;在模块设计方面,强调"可拿去性",即模块应该能适应不同的运行环境。djyos系统融合现成模块的能力,除了与传统操作系统一样提供并发运行能力外,等多地考虑支持程序设计者组合现有模块成为一个新产品,以及设计可组合模块的能力。djyos有许多特性支持拿来拿去主义,泛设备管理器就是一个典型的、支持拿来主义的模块之一。
按djyos的视点,每一个应用程序模块面对的运行环境,不仅仅包括硬件和操作系统,还包括其他软件模块。即使硬件和操作系统没有任何变化,如果产品中其他模块发生了变化,也看做是运行环境发生了变化,djyos强调要软件模块适应这种变化。一个企业,往往有几十几百种系列化的产品型号,这些型号可能建立在相同的硬件和操作系统平台上的,仅仅是应用程序模块的组合和配置不一样。对这样的企业来说,软件模块的灵活组合能力非常重要。传统操作系统的driver架构,是设计来让应用程序以标准的方式访问硬件,屏蔽硬件平台的差异性,driver的使用者和被驱动者有明显的层次关系。而djyos把应用程序的其他模块也看做环境,driver是用于屏蔽整个环境差异的。djyos从软硬件联合设计的角度出发,软件模块、硬件模块、软硬件相结合的模块之间没有层次关系,而统一称之为系统功能模块。因此driver架构也不分层次,driver的使用者和被操作者是平等的关系,一个应用程序模块通过driver提供标准的与其他模块互相访问的接口,只要企业内所有模块都遵循这个接口,那么这个企业内的所有软件模块都可以灵活组合。
8.实时的malloc函数在RTOS中,通常认为malloc函数是非实时组件,因为即使有充足的内存,malloc函数的执行时间也不可预计,不符合实时系统要求执行时间和结果均可预计的原则。但是djyos的内存管理,在一定条件下是实时的,只要在系统设计时,配备充足的内存,malloc的执行时间是快速而且可以预计的,而在只运行一个应用程序的实时系统中,内存不枯竭是容易做到的。djyos的内存分配使用双金字塔的检索结构,以页为单位,在4G寻址空间,页尺寸为1K,CPU字长是32的系统中,只需要经过5次搜索(共5次比较、5次乘法和5次加法)就可以定位一个空闲页,速度是相当快的。
除实时特性外,djyos的内存管理还能在一定程度上防止内存泄漏,而且malloc函数允许在中断ISR中调用。