选择实时操作系统(RTOS)的相关问题
姓名:朱硕雅
学号:14020120008
转载自http://mp.weixin.qq.com/s?__biz=MzAxNDAyMzc0Mg==&mid=2683462191&idx=2&sn=6ffbc07273f118be97e265e21ec5cb26&chksm=819f6f7eb6e8e668f4ae3f11090a3ddc4e984b0217d40590a9b4e6128d66ec903eebbb53cc5e&scene=21#wechat_redirect有修改
【嵌牛导读】:公司里做项目,嵌入式系统大大小小,到处都是,便需要对实时操作系统(RTOS)引入选择有初步认识
【嵌牛鼻子】:嵌入式,实时操作系统
【嵌牛提问】:(1)引入RTOS?
(2)是否需要RTOS?
(3)如何选择RTOS?
【嵌牛正文】:
成本主要是 RTOS 的版费、学习成本。这个差别可大了,有些操作系统,如商业的VxWorks、QNX、Lynx、uC/OS,贵啊,但拍了银子,人家肯定会教您上手的。但很多操作系统,如 FreeRTOS、 RTEMS、ecos、RT-Thread,商业使用几乎是没有成本的,也没有任何的版权问题。撇开这些商业收费的 RTOS 不谈,就谈这些开源免费的 RTOS,成本主要是学习成本了。如RTEMS这种操作系统就不太好学,资料少,本身的复杂度也高;如 FreeRTOS,小巧,研究的人也多,本身代码也不复杂,学习曲线不陡峭,很容易爬上去。
可靠性是靠时间沉淀的。市场上不乏一些后起之秀,如rt-thread,相比 rtems 这种鼻祖类的 rtos,还稍显稚嫩。这并不意味这我们什么都选择 rtems, 那 rt-thread 怎么发展?对于小型的项目,可以试一试。大型项目,为了减少技术上的风险,还是谨慎为妙。
实时性,这个应该是 RTOS 的看家本领,我初学 rtos 的时候,好喜欢看牛人搞得 RTOS 对比表格。上下文切换时间啊,中断响应时延啊……总喜欢挑那些时间最小的系统……但后来我知道了,事实上不是几个对比表格就能说清楚问题的。下面会详细说到这些问题。
工具链,它往往决定我们开发的效率,和最终产品交付的质量。有一些 RTOS 没那么幸运,没有让你选择工具链的权利,就算有,也需要付出很大的代价。如 RTEMS 采用GNU的工具链,gnu 的工具链不好用,我就尝试过把 rtems 移到 iar ewarm 下。后来,搞到一半的时候,不得不放弃,付出的精力已经超出了我的承受范围。但 freeRTOS、uC/OS 这类小 RTOS,只要编译器支持编译可重入代码就可以,这条只有老掉牙的编译器不行。所以基本上是个C编译器都可以做Free RTOS、uC/OS的编译。
模块丰富,有没有TCP/IP协议栈、文件系统、CAN协议栈、图形界面等。当然这个都不是必须的,对于简单的产品,可能这些模块都用不到。对于复杂的系统,这些集成好的模块,会大大节省开发时间。自己也可以移植相关的模块,可能会有几个切实的问题不好解决:模块因为不符合 rtos 的设计思想,会对整体的实时性造成损害;也可能因为模块使用的库,和 rtos 使用的库相冲突……
内核 RAM、ROM 的占用量实际上要求 Rtos 高度可裁剪。不是所有内核裁剪到最后都能满足要求,RTOS 都有个最低的 RAM、ROM 要求,只剩一些最基本的服务。每加一个特性会增加一些资源,可以查阅相关资料得到这方面信息,确定系统资源可以保证顺畅的使用该 RTOS。
支持,如果是商业系统,那不用担心,既然付了银子,人家肯定保证实施过程的顺畅。如果是开源系统,开发团队没有像样的 rtos 专家可不行。虽然 rtos 系统都是相通的,了解另外一个 rtos 很快,但有时候也不尽然。RTEMS 这么复杂的 RTOS 搞懂了,去弄 freeRTOS、uC/OS、rt-Thread 小麻雀,自然没问题;要是弄 QNX、VxWorks、Lynx,还是要费点功夫。 RTOS 在开发过程中会遇到很多问题,比如栈的估算、任务优先级的设计、内存的设计、实时性的设计等,都是很不好弄的问题。最好团队内有相关 RTOS 的专家,要是学习的话无所谓,研发产品和系统的话,那就是大问题了。
(4)几种嵌入式RTOS的分析与比较
1). 4种操作系统的介绍
1.1 VxWorks
VxWorks是美国WindRiver公司的产品,是目前嵌入式系统领域中应用很广泛,市场占有率比较高的嵌入式操作系统。VxWorks实时操作系统由400多个相对独立、短小精悍的目标模块组成,用户可根据需要选择适当的模块来裁剪和配置系统;提供基于优先级的任务调度、任务间同步与通信、中断处理、定时器和内存管理等功能,内建符合POSIX(可移植操作系统接口)规范的内存管理,以及多处理器控制程序;并且具有简明易懂的用户接口,在核心方面甚至可以微缩到8 KB。
1.2 μC/OS-II
μC/OS-II是美国嵌入式系统专家Jean J.Labrosse用C语言编写的一个结构小巧、抢占式的多任务实时内核。μC/OS-II能管理64个任务,并提供任务调度与管理、内存管理、任务间同步与通信、时间管理和中断服务等功能,具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点。
1.3 μClinux
μClinux是一种优秀的嵌入式Linux版本,其全称为micro-control Linux,从字面意思看是指微控制Linux。同标准的Linux相比,μClinux的内核非常小,但是它仍然继承了Linux操作系统的主要特性,包括良好的稳定性和移植性、强大的网络功能、出色的文件系统支持、标准丰富的API,以及TCP/IP网络协议等。因为没有MMU内存管理单元,所以其多任务的实现需要一定技巧。
1.4 eCos
eCos(embedded Configurable operating system),即嵌入式可配置操作系统。它是一个源代码开放的可配置、可移植、面向深度嵌入式应用的实时操作系统。最大特点是配置灵活,采用模块化设计,核心部分由小的组件构成,包括内核、C语言库和底层运行包等。每个组件可提供大量的配置选项(实时内核也可作为可选配置),使用eCos提供的配置工具可以很方便地配置,并通过不同的配置使得eCos能够满足不同的嵌入式应用要求。
1.5FreeRTOS:
以前对FreeRTOS的印象还不错,就因为免费,最近上官网仔细看过以后发现它用的是修改版GPL2,商用确实是免费的,但是必须告知用户你的产品用了FreeRTOS,并且如果用户要求就必须提供源代码。
如果要不谈我用的什么系统,也不想提供源代码,就的付费给它,改授权变成OpenRTOS。
还有更好的呢!如果想要更多的功能,更全的协议栈,更完善完整的安全性,请付更多的钱得到SafeRTOS!看个API文档都要收钱,要其他模块也要收钱(FS,TCP)。要不就自己费点劲移植吧。另外,功能也比较简单,只能支持:队列,信号量和互斥。但是收费版SafeRTOS应该不错,只是不拿钱就见不着(流明的CM3部分型号内建了SafeRTOS的API,出厂就有可以直接用,这个不错。)
最小系统:ROM 6K RAM 2K
/*补充内容*/
FreeRTOS和OpenRTOS
FreeRTOS和OpenRTOS的共享相同的源码,只是 OpenRTOS 为 FreeRTOS 披上’commercial and legal wrapper’‘
用户从FreeRTOS更新到OpenRTOS主要有两个原因:
(1)为了克服FreeRTOS修改版的GPL许可证限制。
(2)为了获得额外的服务,如专业的技术支持,高质量的中间件,培训,咨询和相应的工具
FreeRTOS修改版的GPL许可证限制
修改版的GPL许可证有如下几个缺陷(There are several reasons why developers may find the FreeRTOS modified GPL licence restrictive.)
(1)公司可能有一个全面禁止在他们的项目中使用GPL授权的软件。
(2)他们可能需要IP赔偿。
(3)他们可能更愿意在他们的产品中,避免FreeRTOS的许可证要求承认他们使用FreeRTOS的。
一个OPENRTOS许可证删除了 修改后的GPL的限制,提供知识产权保障,并允许开发者保持匿名。
FreeRTOS和SafeRTOS
SafeRTOS也是基于FreeRTOS的,但是和FreeRTOS不同,被安全方面的专家做了重新设计。
SAFERTOSwas initially certified in 2007 by TüV SüD to IEC 61508-3 SIL 3, the highest level possible for a software only component.
Today SAFERTOShas grown to be a leading safety critical RTOS solution supporting a wide range of international design safety standards, including:
IndustrialIEC 61508 (2010)
RailwayEN 50128
MedicalIEC 62304/FDA 510K
NuclearIEC 61513, IEC 62138, ASME NQA-1 2008
ProcessIEC 61511
AutomotiveISO 26262
AerospaceDO178B
2) 性能分析与比较
任务管理、任务及中断间的同步与通信机制、内存管理、中断管理、文件系统、对硬件的支持和系统移植这几方面是实时操作系统的主要性能。下面就从这几个方面着手对上述4种操作系统进行分析与比较。
2.1 任务管理
任务管理是嵌入式实时操作系统的核心和灵魂,决定了操作系统的实时性能。它通常包含优先级设置、多任务调度机制和时间确定性等部分。
优先级设置
嵌入式操作系统支持多任务,每个任务都具有优先级,任务越重要,赋予的优先级应越高。优先级的设置分为静态优先级和动态优先级两种。静态优先级指的是每个任务在运行前都被赋予一个优先级,而且这个优先级在系统运行期间正常情况下是不能改变的,但允许通过系统调函函数改变任务的优先级;动态优先级则是指每个任务的优先级(特别是应用程序的优先级)在系统运行时可以动态地改变,这种改变是调度算法决定的,而非通过系统调用人为改变的。
多任务调度机制
任务调度主要是协调任务对CPU资源的争夺使用。对系统资源非常匮乏的嵌入式系统来说,任务调度尤为重要,它直接影响到系统的实时性能。通常,多任务调度机制分为基于优先级抢占式调度和时间片轮转调度。
基于优先级抢占式调度(PBP,Priority Based and Preemptive):系统中每个任务都有一个优先级,内核总是将CPU分配给处于就绪态的优先级最高的任务运行。如果系统发现就绪队列中有比当前运行任务更高的优先级任务,就把当前运行任务置于就绪队列中,调入高优先级任务运行。系统采用优先级抢占方式进行调度,可以保证重要的突发事件及时得到处理。
时间片轮转调度(RR,Round Robin) :让优先级相同的处于就绪状态的任务按时间片使用CPU,以防止同优先级的某一任务长时间独占CPU。
在一般情况下,嵌入式实时操作系统采用基于优先级抢占式调度与时间片轮转调度相结合的调度机制。
时间的可确定性
嵌入式实时操作系统函数调用与服务的执行时间应具有可确定性。系统服务的执行时间不依赖于应用程序任务的多少。基于此特征,系统完成某个确定任务的时间是可预测的。表1具体列出了4种操作系统的调度机制。
4种嵌入式实时操作系统都支持多任务,只是在支持任务数量上和任务调度机制上有所不同。VxWorks具有高效的任务管理功能,它支持多任务,可分配256个优先级,支持优先级抢占式调试和时间片轮转调度,实时性最好。μC/OS-II内核是针对实时系统的要求设计实现的,只支持基于固定优先级抢占式调度;调度方法简单,可以满足较高的实时性要求。μClinux在结构上继承了标准Linux的多任务实现方式,分为实时进程和普通进程,分别采用先来先服务和时间片轮转调度;仅针对中低档嵌入式CPU特点进行改良,且不支持内核抢占。eCos调度方法丰富,提供了两种基于优先级的调度器(即位图调度器和多级队列调度器),允许用户在进行配置时选择其中一个凋度器,适应性好。
2.2 任务及中断间的同步与通信机制
实时操作系统的功能一般要通过若干任务和中断服务程序共同完成。任务与任务之间、任务与中断间任务及中断服务程序之间必须协调动作,互相配合,这就涉及任务间的同步与通信问题。嵌入式实时操作系统通常是通过信号量Semaphere、互斥信号量Mutex、事件标志Event和异步信号Signal来实现同步,通过消息邮箱MailBox、消息队列没Message、管道Pipe和共享内存Share Mem来提供通信服务。由于互斥信号量的使用,带来了实时操作系统中常见的优先级反转问题。优先级反转是一种不确定的延迟形式,当高优先级任务企图访问已被低优先级占有的共享资源时,必须等待低优先级任务释放共享资源;如果这时低优先级任务被一个或多个中优先级任务抢占,那么高优先级任务被延迟的时间将更进一步延长,实时性难以保证。因此,应采取相关措施以尽鼍避免出现优先级反转问题。实时系统通常采用优先级继承和优先级置顶机制。
优先级继承是指拥有互斥信号量的任务被提升到与下一个在等待该互斥信号量的最高优先级任务相同的优先级;优先级置顶是指获得互斥量的任务将其优先级提升到一个事先规定好的值。表2为4种操作系统的同步与通信机制的比较。
4种系统都具有灵话的任务间同步与通信机制,都可以通过信号量、消息队列来实现同步与通信,但是VxWorks与μClinux都不支持邮箱和事件标志,而且除了μClinux和eCos中的位图调度器,其他操作系统都采取了措施抑制优先级反转。
2.3 内存管理
内存管理主要包括:内存分配原则,存储保护和内存分配方式。
内存分配原则
内存分配原则包括快速性、可靠性和高效性。其中,快速性要求内存分配过程要尽可能快,所以一般采用简单、快速的分配算法;可靠性指的是内存分配的请求必须得到满足;系统强调高效性的要求,不仅仅是对系统成本的要求,而且由于系统本身可配置的内存容量也是很有限的,所以要尽可能地避免浪费。嵌入式系统通常会根据特定的需求对内存分配方案进行规划,从而避免内存碎片。
存储保护
通常在操作系统的内存中既有系统程序也有用户程序,为了使两者都能正常运行,避免程序间相互干扰,需要对内存中的程序和数据进行保护。存储保护通常需要硬件支持,在很多系统中都采用MMU,并结合软件实现;但由于嵌入式系统的成本限制内核和用户程序通常都在相同的内存空间中。因此是否支持存储保护一方面取决于CPU是否支持MMU及不同的运行级别,如ARM7TDMI核不支持MMU,大多数DSP都不支持MMU和运行级别;另一方面依赖于操作系统是否在软件上进行支持,uC/OS、eCos等本身就不支持虚拟内存管理。VxWorks也有不同的版本,6.0版本以下就不支持MMU。
内存分配方式
内存分配方式可分为静态分配和动态分配。静态分配是在程序运行前一次性分配给相应内存,并且在程序运行期间中不允许再申请或在内存中移动;动态分配则允许在程序运行整个过程中进行内存分配。静态分配使系统失去了灵活性,但对于实时性要求比较高的系统是必需的,通常情况下这些系统的内存有限,用户的全局数据都会精心规划,只有内核本身会使用一些动态内存;而动态分配赋予了系统设计者更多自主性,可以灵活地调整系统的功能。
VxWorks对内存的使用采用的是Flat Mode,可被静态或动态链接。VxWorks为用户提供了两种内存区域Region和Partition。Region是变长的内存区,用户可以从创建的Region中分配Segment,其特点是容易产生碎片,但灵活并且不浪费;Partition是定长的内存区,用户可以从刨建的Partition中分配Buffer,其特点是不会产生碎片,效率高但是易浪费。VxWorks采用最先算法分配内存。
μC/OS-II把连续的大块内存按分区来管理,每个分区中都包含整数个大小相同的内存块,但不同分区之间内存的太小可以不同。用户动态分配内存时,只须选择一个适当的分区,按块来分配内存,释放时将该块放回到以前所属的分区,这样就消除了因多次动态分配和释放内存所引起的碎片问题。
μClinux是针对没有MMU的处理器设计的,不能使用处理器的虚拟内存管理技术,只能采用实存储器管理策略。系统使用分页内存分配方式,在启动时对实际存储器进行分页。系统对内存的访问是直接的,操作系统对内存空间没有保护,多个进程可共享一个运行空间,所以,即使是一个无特权进程调用一个无效指针也会触发一个地址错误,并有可能引起程序崩溃甚至系统崩溃。
eCos对内存分配既不分段也不分页,而是采用一种基于内存池的动态内存分配机制。通过两种内存池来实现两种内存管理方法:一种是变长的内存池;另一种是定长的内存池,类似于VxWorb的管理方案。表3为4种操作系统内存管理的比较。
2.4 中断管理
中断管理是实时系统中一个很重要的部分,系统经常通过中断与外部事件交互。主要考虑是否支持中断嵌套、中断处理机制、中断延时等。
VxWorks的中断管理
VxWorks操作系统中断管理采用中断处理与普通任务分别在不同栈中处理的中断处理机制,使得中断只会引发一些关键寄存器的存储,而不会导致任务的上下文切换,从而极大地缩短了中断延时。同时,VxWorks的中断处理程序一般在最短时间内通告中断的发生,而将其他的非实时处理尽量放入被引发的中断服务任务中来完成,这也缩短了中断处理的时间,可有效减少中断延时。所有中断处理程序使用相同的中断堆栈。为了能处理最坏情况下的中断嵌套,必须分配足够大的中断堆栈空间。
μC/OS-II的中断管理
μC/OS-II中断处理比较简单。一个中断向量上只能挂一个中断服务子程序ISR,而且用户代码必须都在ISR中完成。ISR需要做的事情越多,中断延时也就越长。是否支持中断嵌套取决于具体实现,如在ARM处理器上当选择中断嵌套时需要切换不同的处理器模式,实现起来也比较麻烦。
μClinux的中断管理
μClinux操作系统将中断处理分为两部分:顶半处理和底半处理。在顶半处理中,必须关中断运行,且仅进行必要的、非常少、速度快的处理,其他处理交给底半处理;底半处理执行那些复杂、耗时的处理,而且允许被中断。通常在硬件中断返回的时候会执行底半部的软中断,若软中断太多则会交给专门的内核处理任务处理,此时中断返回,避免由于中断运行时间过长影响其它其他进程。因此在顶半部中断是不会嵌套的。所有的中断服务下半部将顺序执行。所有的中断处理程序共用系统堆栈。
eCos的中断管理
eCos使用了分层式中断处理机制,把中断处理分为传统的ISR和滞后中断服务程序DSR。类似于μClinux的处理机制,这种机制可以在中断允许时运行DSR,因此在处理较低优先级中断时允许高优先级的中断和处理。为了极大地缩短中断延时,ISR应当可以快速运行。如果中断引起的服务量少,则ISR可以单独处理中断;如果中断服务复杂,则ISR只屏蔽中断源,然后交由DSR处理。
2.5 文件系统
所谓"文件系统"是指负责存取和管理文件信息的机构,也可以说是负责文件的建立、撤销、组织、读写、修改、复制,以及对文件管理所需的其他资源实施管理的软件部分。
VxWorks操作系统在文件系统与设备驱动程序之间使用一种标准的I/O口操作接口,且支持MS-DOS、RT-11、RFS、CD-ROM、RAW等文件系统。这样,在单个VxWorks操作系统中可以运行多个相同或不同种类的文件系统。
μC/OS-II是面向中小型嵌入式系统的,即使包含全部功能,编译后内核也不到10 KB,所以系统本身并没有提供对文件系统的支持。但是μC/OS-II具有良好的扩展性能,如果需要也可自行加入文件系统的内容。
μClinux继承了Linux完善的文件系统性能,采用VFS机制,可以支持ROMFS、NFS、ext2、MS-DOS、JFFS等文件系统。但一般采用ROMFS文件系统,这种文件系统相对于一般的文件系统(如ext2)占用更少的空间。但是ROMFS文件系统不支持动态擦写保存,对于系统需要动态保存的数据须采用虚拟RAM盘/JFFS的方法进行处理。
eCos操作系统的可配置性非常强大,用户可以自己加入所需的文件系统。
2.6 对硬件的支持
VxWorks、μC/OS-II、μClinux和eCos这4种操作系统都支持当前流行的大部分嵌入式CPU。μC/OS-II支持从8位到32位的CPU,VxWorks、μClinux和eCos可以在16位、32位和64位等不同体系结构之间移植。
由于μClinux继承了Linux的大部分性能,所以至少需要512KB的RAM空间,lMB的ROM/Flash空间;而μC/OS-II和eCos由于本身内核就很小,经过裁剪后的代码最小可以分别为2 KB和10 KB,所需的最小数据RAM空间分别为4 KB和10 KB。总的来说,4种系统对硬件的要求比较低,比较经济。具体比较如表4所列。
2.7 系统移植
嵌入式操作系统移植的目的是使嵌入式操作系统能在某个微处理器或微控制器上运行。4种系统中VxWorks是商用操作系统的有很多API函数及相关技术支持,所以移植和二次开发比较容易,但是移植成本较高。其他3种系统的结构化设计便于把与处理器相关的部分分离出来,所以被移植到新的处理器上也是可能的。μC/OS-II的移植相对比较简单,只需要修改与处理器相关的代码就可以了。μClinux是Linux针对嵌入式系统的一种改良,其结构比较复杂。移植μClinux,目标处理器除了应满足μC/OS-II移植所需的条件外,还需要足够容量的外部ROM和RAM。eCos系统的可移植性明显比μC/OS-II和μClinux好。在eCos系统中,每个硬件平台都有一个单独的目录,用于存放引对这一硬件平台的硬件抽象层的代码和配置信息;而μClinux的硬件抽象层的代码则分布在好几个目录中,通过命令来选择不同硬件平台的代码。所以,修改eCos代码相对简单,移植也相对容易。
2.8 结论
这4种嵌入式实时操作系统在嵌入式系统的应用非常广泛,但是又具有各自的特点。根据上述比较,归纳出各自的适用领域。
VxWorks是一套类似于Unix的实时操作系统,它内建了符合POSIX规范的内存管理,以及多处理器控制程序,并且具有简明易懂的用户接口,在核心方面甚至可以微缩到8 KB。它由400多个相对独立的、短小精悍的目标模块组成,用户可根据需要选择适当模块来裁剪和配置系统,有效地保证了系统的安全性和可靠性。它被广泛地应用在通信、军事、航空、航天等高尖技术及实时性要求极高的领域,尤其是在许多关键应用方面,VxWorks还是一枝独秀。例如,美国波音公司就在其最新的787客机中采用了此操作系统;而在外层空间探索领域,VxWorks则一直是美国太空总署NASA的最爱。
μC/OS-II是一个结构简单、功能完备和实时性很强的嵌入式操作系统内核,适合于广大的嵌入式系统开发人员和爱好者入门学习,以及高校教学和科研。μC/OS-II很适合开发那些对系统要求不是很苛刻,且RAM和ROM有限的各种小型嵌入式系统设备。
μClinux最大特点在于针对无MMU处理器设计,可以利用功能强大的Linux资源,因此适合开发对时间要求不高的小容量、低成本的各类产品,特别适用于开发与网络应用密切相关的嵌入式设备或者PDA设备。例如,CISCO公司的2500/3000/4000路由器就是基于μClinux操作系统开发的。
eCos最大特点是配置灵活,而且是面向深度嵌入式应用的,很适合用于一些商业级或工业级对成本敏感的嵌入式系统,例如消费电子类领域中的一些应用。
推荐阅读
-
openEuler郑州用户组成立!openEuler与hyperfusion携手共建河南地区用户生态 - 开幕致辞 超融合操作系统业务总经理、openEuler委员会成员蒋振华先生为本次活动致辞。 在本次活动的致辞中,他提到,作为openEuler社区早期的成员,超融合见证了openEuler从成立到在各行业商业落地,再到跨越生态拐点的过程,感谢openEuler提供了一个全产业链共同创新的平台,共同推动创新技术的商业落地。 同时,本次活动得到了郑州市郑东新区大数据管理局、郑州中原科技城投资服务局的大力支持。 郑东新区大数据管理局曹光远 在活动致辞中表示,openEuler的应用和*应用设施的深度优化,为郑东新区数字化转型提供了安全、可靠、高性能的技术基础;郑州中原科技城招商服务局王林表示,郑东新区欢迎所有openEuler生态相关企业扎根当地,围绕openEuler社区共同发展,形成合力。 openEuler社区及运维功能介绍 openEuler技术委员会委员胡峰 openEuler技术委员会委员胡峰先生在本次活动中介绍了openEuler社区目前发展的整体情况,并重点从技术层面介绍了openEuler的运维功能。 openEuler 晚会 胡峰先生介绍智能运维工具 A-Ops 和 openEuler gala、 阿波罗 Apollo、智能漏洞管理解决方案等新功能,以及涵盖各种运维场景的精品运维组件。在*交流环节,许多用户就目前使用的 openEuler 在*交流环节,许多用户就自己在使用openEuler过程中遇到的一些问题与胡峰先生进行了进一步的交流。 软硬结合,构建多样化算力操作系统 Hyperfusion 基于 openEuler 的基础上,结合自身软硬件技术积累,推出了富讯服务器操作系统 FusionOS FusionOS. FusionOS 首席架构师张海亮 分享了 FusionOS FusionOS首席架构师张海亮分享了FusionOS的软硬件协同优势、卓越的性能和可靠性,以及FusionOS在金融、运营商、*、互联网等行业的实践案例,引起了众多用户的兴趣,分享结束后,不少参会者就FusionOS的特点向讲师提问并进行了交流。
-
云服务器+家用电脑(无公网 IP)Pinode 节点部署教程--理论上,无论你身在何处,只要能上网,就能运行一个固定 IP 的 Pi 节点节点!(注:不能直接部署独立云服务器)本方案相对运营商公网 IP 有以下优势:拥有稳定的固定 IP(阿里云 IP),解决了运营商不分配公网 IP 或分配动态 IP 的问题 ②节点部署在本地电脑上,相对安全。因为是使用阿里云的专网,稳定性也很强。希望对大家有用,帮助大家解决没有公网的节点部署问题。第一步:环境准备 1、本地电脑配置: ①操作系统:推荐 WIN10 专业版(目前节点容器只支持 2004 专业版) ②内存:推荐 4G 及以上 建议:https://item.taobao.com/item.htm?spm=a2126o.success.0.0.61 b94831SbZESt&id=6346663414282,阿里云服务器租用:阿里云(推荐1核2G以上,ECS共享s6,带宽3-5M即可,以下两个链接都可以,选择一个合适的即可)https://www.aliyun.com/minisite/ goods?userCode=is7i4iav
-
windows下进程间通信的(13种方法)-摘 要 本文讨论了进程间通信与应用程序间通信的含义及相应的实现技术,并对这些技术的原理、特性等进行了深入的分析和比较。 ---- 关键词 信号 管道 消息队列 共享存储段 信号灯 远程过程调用 Socket套接字 MQSeries 1 引言 ---- 进程间通信的主要目的是实现同一计算机系统内部的相互协作的进程之间的数据共享与信息交换,由于这些进程处于同一软件和硬件环境下,利用操作系统提供的的编程接口,用户可以方便地在程序中实现这种通信;应用程序间通信的主要目的是实现不同计算机系统中的相互协作的应用程序之间的数据共享与信息交换,由于应用程序分别运行在不同计算机系统中,它们之间要通过网络之间的协议才能实现数据共享与信息交换。进程间通信和应用程序间通信及相应的实现技术有许多相同之处,也各有自己的特色。即使是同一类型的通信也有多种的实现方法,以适应不同情况的需要。 ---- 为了充分认识和掌握这两种通信及相应的实现技术,本文将就以下几个方面对这两种通信进行深入的讨论:问题的由来、解决问题的策略和方法、每种方法的工作原理和实现、每种实现方法的特点和适用的范围等。 2 进程间的通信及其实现技术 ---- 用户提交给计算机的任务最终都是通过一个个的进程来完成的。在一组并发进程中的任何两个进程之间,如果都不存在公共变量,则称该组进程为不相交的。在不相交的进程组中,每个进程都独立于其它进程,它的运行环境与顺序程序一样,而且它的运行环境也不为别的进程所改变。运行的结果是确定的,不会发生与时间相关的错误。 ---- 但是,在实际中,并发进程的各个进程之间并不是完全互相独立的,它们之间往往存在着相互制约的关系。进程之间的相互制约关系表现为两种方式: ---- (1) 间接相互制约:共享CPU ---- (2) 直接相互制约:竞争和协作 ---- 竞争——进程对共享资源的竞争。为保证进程互斥地访问共享资源,各进程必须互斥地进入各自的临界段。 ---- 协作——进程之间交换数据。为完成一个共同任务而同时运行的一组进程称为同组进程,它们之间必须交换数据,以达到协作完成任务的目的,交换数据可以通知对方可以做某事或者委托对方做某事。 ---- 共享CPU问题由操作系统的进程调度来实现,进程间的竞争和协作由进程间的通信来完成。进程间的通信一般由操作系统提供编程接口,由程序员在程序中实现。UNIX在这个方面可以说最具特色,它提供了一整套进程间的数据共享与信息交换的处理方法——进程通信机制(IPC)。因此,我们就以UNIX为例来分析进程间通信的各种实现技术。 ---- 在UNIX中,文件(File)、信号(Signal)、无名管道(Unnamed Pipes)、有名管道(FIFOs)是传统IPC功能;新的IPC功能包括消息队列(Message queues)、共享存储段(Shared memory segment)和信号灯(Semapores)。 ---- (1) 信号 ---- 信号机制是UNIX为进程中断处理而设置的。它只是一组预定义的值,因此不能用于信息交换,仅用于进程中断控制。例如在发生浮点错、非法内存访问、执行无效指令、某些按键(如ctrl-c、del等)等都会产生一个信号,操作系统就会调用有关的系统调用或用户定义的处理过程来处理。 ---- 信号处理的系统调用是signal,调用形式是: ---- signal(signalno,action) ---- 其中,signalno是规定信号编号的值,action指明当特定的信号发生时所执行的动作。 ---- (2) 无名管道和有名管道 ---- 无名管道实际上是内存中的一个临时存储区,它由系统安全控制,并且独立于创建它的进程的内存区。管道对数据采用先进先出方式管理,并严格按顺序操作,例如不能对管道进行搜索,管道中的信息只能读一次。 ---- 无名管道只能用于两个相互协作的进程之间的通信,并且访问无名管道的进程必须有共同的祖先。 ---- 系统提供了许多标准管道库函数,如: pipe——打开一个可以读写的管道; close——关闭相应的管道; read——从管道中读取字符; write——向管道中写入字符; ---- 有名管道的操作和无名管道类似,不同的地方在于使用有名管道的进程不需要具有共同的祖先,其它进程,只要知道该管道的名字,就可以访问它。管道非常适合进程之间快速交换信息。 ---- (3) 消息队列(MQ) ---- 消息队列是内存中独立于生成它的进程的一段存储区,一旦创建消息队列,任何进程,只要具有正确的的访问权限,都可以访问消息队列,消息队列非常适合于在进程间交换短信息。 ---- 消息队列的每条消息由类型编号来分类,这样接收进程可以选择读取特定的消息类型——这一点与管道不同。消息队列在创建后将一直存在,直到使用msgctl系统调用或iqcrm -q命令删除它为止。 ---- 系统提供了许多有关创建、使用和管理消息队列的系统调用,如: ---- int msgget(key,flag)——创建一个具有flag权限的MQ及其相应的结构,并返回一个唯一的正整数msqid(MQ的标识符); ---- int msgsnd(msqid,msgp,msgsz,msgtyp,flag)——向队列中发送信息; ---- int msgrcv(msqid,cmd,buf)——从队列中接收信息; ---- int msgctl(msqid,cmd,buf)——对MQ的控制操作; ---- (4) 共享存储段(SM) ---- 共享存储段是主存的一部分,它由一个或多个独立的进程共享。各进程的数据段与共享存储段相关联,对每个进程来说,共享存储段有不同的虚拟地址。系统提供的有关SM的系统调用有: ---- int shmget(key,size,flag)——创建大小为size的SM段,其相应的数据结构名为key,并返回共享内存区的标识符shmid; ---- char shmat(shmid,address,flag)——将当前进程数据段的地址赋给shmget所返回的名为shmid的SM段; ---- int shmdr(address)——从进程地址空间删除SM段; ---- int shmctl (shmid,cmd,buf)——对SM的控制操作; ---- SM的大小只受主存限制,SM段的访问及进程间的信息交换可以通过同步读写来完成。同步通常由信号灯来实现。SM非常适合进程之间大量数据的共享。 ---- (5) 信号灯 ---- 在UNIX中,信号灯是一组进程共享的数据结构,当几个进程竞争同一资源时(文件、共享内存或消息队列等),它们的操作便由信号灯来同步,以防止互相干扰。 ---- 信号灯保证了某一时刻只有一个进程访问某一临界资源,所有请求该资源的其它进程都将被挂起,一旦该资源得到释放,系统才允许其它进程访问该资源。信号灯通常配对使用,以便实现资源的加锁和解锁。 ---- 进程间通信的实现技术的特点是:操作系统提供实现机制和编程接口,由用户在程序中实现,保证进程间可以进行快速的信息交换和大量数据的共享。但是,上述方式主要适合在同一台计算机系统内部的进程之间的通信。 3 应用程序间的通信及其实现技术 ---- 同进程之间的相互制约一样,不同的应用程序之间也存在竞争和协作的关系。UNIX操作系统也提供一些可用于应用程序之间实现数据共享与信息交换的编程接口,程序员可以通过自己编程来实现。如远程过程调用和基于TCP/IP协议的套接字(Socket)编程。但是,相对普通程序员来说,它们涉及的技术比较深,编程也比较复杂,实现起来困难较大。 ---- 于是,一种新的技术应运而生——通过将有关通信的细节完全掩盖在某个独立软件内部,即底层的通讯工作和相应的维护管理工作由该软件内部来实现,用户只需要将通信任务提交给该软件去完成,而不必理会它的具体工作过程——这就是所谓的中间件技术。 ---- 我们在这里分别讨论这三种常用的应用程序间通信的实现技术——远程过程调用、会话编程技术和MQSeries消息队列技术。其中远程过程调用和会话编程属于比较低级的方式,程序员参与的程度较深,而MQSeries消息队列则属于比较高级的方式,即中间件方式,程序员参与的程度较浅。 ---- 4.1 远程过程调用(RPC)
-
【Netty】「萌新入门」(七)ByteBuf 的性能优化-堆内存的分配和释放都是由 Java 虚拟机自动管理的,这意味着它们可以快速地被分配和释放,但是也会产生一些开销。 直接内存需要手动分配和释放,因为它由操作系统管理,这使得分配和释放的速度更快,但是也需要更多的系统资源。 另外,直接内存可以映射到本地文件中,这对于需要频繁读写文件的应用程序非常有用。 此外,直接内存还可以避免在使用 NIO 进行网络传输时发生数据拷贝的情况。在使用传统的 I/O 时,数据必须先从文件或网络中读取到堆内存中,然后再从堆内存中复制到直接缓冲区中,最后再通过 SocketChannel 发送到网络中。而使用直接缓冲区时,数据可以直接从文件或网络中读取到直接缓冲区中,并且可以直接从直接缓冲区中发送到网络中,避免了不必要的数据拷贝和内存分配。 通过 ByteBufAllocator.DEFAULT.directBuffer 方法来创建基于直接内存的 ByteBuf: ByteBuf directBuf = ByteBufAllocator.DEFAULT.directBuffer(16); 通过 ByteBufAllocator.DEFAULT.heapBuffer 方法来创建基于堆内存的 ByteBuf: ByteBuf heapBuf = ByteBufAllocator.DEFAULT.heapBuffer(16); 注意: 直接内存是一种特殊的内存分配方式,可以通过在堆外申请内存来避免 JVM 堆内存的限制,从而提高读写性能和降低 GC 压力。但是,直接内存的创建和销毁代价昂贵,因此需要慎重使用。 此外,由于直接内存不受 JVM 垃圾回收的管理,我们需要主动释放这部分内存,否则会造成内存泄漏。通常情况下,可以使用 ByteBuffer.clear 方法来释放直接内存中的数据,或者使用 ByteBuffer.cleaner 方法来手动释放直接内存空间。 测试代码: public static void testCreateByteBuf { ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(16); System.out.println(buf.getClass); ByteBuf heapBuf = ByteBufAllocator.DEFAULT.heapBuffer(16); System.out.println(heapBuf.getClass); ByteBuf directBuf = ByteBufAllocator.DEFAULT.directBuffer(16); System.out.println(directBuf.getClass); } 运行结果: class io.netty.buffer.PooledUnsafeDirectByteBuf class io.netty.buffer.PooledUnsafeHeapByteBuf class io.netty.buffer.PooledUnsafeDirectByteBuf 池化技术 在 Netty 中,池化技术指的是通过对象池来重用已经创建的对象,从而避免了频繁地创建和销毁对象,这种技术可以提高系统的性能和可伸缩性。 通过设置 VM options,来决定池化功能是否开启: -Dio.netty.allocator.type={unpooled|pooled} 在 Netty 4.1 版本以后,非 Android 平台默认启用池化实现,Android 平台启用非池化实现; 这里我们使用非池化功能进行测试,依旧使用的是上面的测试代码 testCreateByteBuf,运行结果如下所示: class io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeDirectByteBuf class io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf class io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeDirectByteBuf 可以看到,ByteBuf 类由 PooledUnsafeDirectByteBuf 变成了 UnpooledUnsafeDirectByteBuf; 在没有池化的情况下,每次使用都需要创建新的 ByteBuf 实例,这个操作会涉及到内存的分配和初始化,如果是直接内存则代价更为昂贵,而且频繁的内存分配也可能导致内存碎片问题,增加 GC 压力。 使用池化技术可以避免频繁内存分配带来的开销,并且重用池中的 ByteBuf 实例,减少了内存占用和内存碎片问题。另外,池化技术还可以采用类似 jemalloc 的内存分配算法,进一步提升分配效率。 在高并发环境下,池化技术的优点更加明显,因为内存的分配和释放都是比较耗时的操作,频繁的内存分配和释放会导致系统性能下降,甚至可能出现内存溢出的风险。使用池化技术可以将内存分配和释放的操作集中到预先分配的池中,从而有效地降低系统的内存开销和风险。 内存释放 当在 Netty 中使用 ByteBuf 来处理数据时,需要特别注意内存回收问题。 Netty 提供了不同类型的 ByteBuf 实现,包括堆内存(JVM 内存)实现 UnpooledHeapByteBuf 和堆外内存(直接内存)实现 UnpooledDirectByteBuf,以及池化技术实现的 PooledByteBuf 及其子类。 UnpooledHeapByteBuf:通过 Java 的垃圾回收机制来自动回收内存; UnpooledDirectByteBuf:由于 JVM 的垃圾回收机制无法管理这些内存,因此需要手动调用 release 方法来释放内存; PooledByteBuf:使用了池化机制,需要更复杂的规则来回收内存; 由于池化技术的特殊性质,释放 PooledByteBuf 对象所使用的内存并不是立即被回收的,而是被放入一个内存池中,待下次分配内存时再次使用。因此,释放 PooledByteBuf 对象的内存可能会延迟到后续的某个时间点。为了避免内存泄漏和占用过多内存,我们需要根据实际情况来设置池化技术的相关参数,以便及时回收内存; Netty 采用了引用计数法来控制 ByteBuf 对象的内存回收,在博文 「源码解析」ByteBuf 的引用计数机制 中将会通过解读源码的形式对 ByteBuf 的引用计数法进行深入理解; 每个 ByteBuf 对象被创建时,都会初始化为1,表示该对象的初始计数为1。 在使用 ByteBuf 对象过程中,如果当前 handler 已经使用完该对象,需要通过调用 release 方法将计数减1,当计数为0时,底层内存会被回收,该对象也就被销毁了。此时即使 ByteBuf 对象还在,其各个方法均无法正常使用。 但是,如果当前 handler 还需要继续使用该对象,可以通过调用 retain 方法将计数加1,这样即使其他 handler 已经调用了 release 方法,该对象的内存仍然不会被回收。这种机制可以有效地避免了内存泄漏和意外访问已经释放的内存的情况。 一般来说,应该尽可能地保证 retain 和 release 方法成对出现,以确保计数正确。
-
哪些是JavaScript选择器的例子?JavaScript选择相关问题
-
选择实时操作系统(RTOS)的相关问题