物联网操作系统碎片化问题解析:CPU、外设、组件与接口的挑战与设计理念
1. 概述
本文以物联网操作系统面临的碎片化问题为主题,从CPU、外设、组件和接口四个方面阐述了物联网操作系统面临的挑战和一些设计理念。以总分1.0来衡量,我认为整个物联网系统的碎片化指数如下:
物联网系统的碎片化从根本上来自于应用需求。这些需求的维度包括:成本、功能、性能、启动速度、功耗、实时性能、安全性等,甚至还有编程语言和接口。有些要求是相互冲突的,例如低成本和高功能。因此,我将应用程序的碎片索引定义为最高的1.0。
单一的硬件架构无法满足多样化的物联网应用需求,导致底层硬件碎片化。其中外设最为严重,我认为其碎片指数为0.9。通过对操作系统的抽象和封装,可以在一定程度上减少硬件碎片的影响。例如CPU的类型有很多,但是经过软件封装后,可以提供更加一致的接口,所以上图中CPU核心的碎片指数是0.4,但是CPU抽象层的碎片指数只有0.2 。
为了满足不同维度的应用需求,物联网操作系统从接口到组件再到内核都变得严重碎片化。同时,操作系统版本本身的演进也进一步导致了碎片化。不同的用户可能使用不同的版本,有的用户甚至根据自己的需求独立演进。
本文还将比较PC硬件平台/桌面操作系统,并分析它们在面临碎片问题时采取的策略。
2. CPU和操作系统内核 2.1 CPU的碎片分析
市场上的CPU种类繁多,每种都有自己的特点。 CPU是通过数字电路实现的。实现是基于CPU的架构设计文档,主要是指令集架构(ISA,Instruction Set Architecture),分为两种:
(1)精简指令集计算(RISC,精简指令集计算)。它只提供最基本的指令,通过多条指令组合可以实现复杂的功能。该架构的CPU实现简单,功耗低。
(2) 复杂指令集计算机(CISC),提供尽可能强大的指令。该架构的CPU实现复杂、高性能、功耗高。
在物联网领域,大部分采用精简指令集架构的CPU,如ARM、MIPS、RISC-V、CSKY等,其中ARM架构处于绝对垄断地位。同时,在IP核授权的产业合作模式下,将CPU架构应用于大量物联网芯片。
每个CPU架构主要包含以下三个部分:
(1)指令集和寄存器。指令集包括跳转、操作、位操作等指令。不同的架构提供不同的指令。同时,为了减少指令占用的内存空间,一些CPU架构设计了更加紧凑的指令,例如ARM的thumb指令和RISC-V的压缩指令。精简指令集架构的一个显着特点是CPU只能操作寄存器中的数据,而不能直接操作内存中的数据。它提供加载和存储指令,用于将数据从内存加载到寄存器或将寄存器数据写入内存,即所谓的加载/存储架构。与复杂指令集CPU相比,精简指令集CPU拥有更多的寄存器,通常为16个或32个。
(2) 异常和中断。异常是由指令触发的同步事件,包括无效指令、访问非法地址、系统调用等。中断由外设触发,用于处理异步事件。精简指令集架构的CPU通常将中断视为异步异常,并且中断和异常在同一个进程中处理。 CPU架构的异常与中断部分包括异常向量表、异常使能与禁止、异常进入与返回、优先级配置等。
(3) 浮点数。硬件提供的浮点计算能力比软件实现的效率更高。 CPU架构的浮点部分包括浮点指令、浮点通用寄存器、浮点控制寄存器等。
虽然物联网芯片基本都采用精简指令集架构CPU,但每种架构都有自己的指令编码、寻址模式、异常处理、自己独特的状态寄存器、控制寄存器以及独特的ABI规范。 。如果开发者需要面对这些复杂的细节,不仅开发门槛会大大提高,开发周期也会拉长。 C/C++语言及其编译器从语言层面实现了一层抽象,但这显然还不够。
2.2 CPU抽象层和内核
CPU运行时,首先从内存中读取一条指令,然后解析该指令并执行相应的操作。该过程以指令单元重复。当中断发生时,跳转到中断入口,处理中断,然后返回到被中断中断的位置。也就是说,从CPU核心的角度来看,只有两种执行流程:一种是主执行流程,一种是中断执行流程,并且都是及时运行的。
传统的裸机编程是基于CPU的运行特性。整个应用程序主要包含一个大的while循环和一个中断处理入口,分别对应CPU的主执行流程和中断执行流程。这种编程模型将所有应用逻辑放在一个大的while循环中,不适合开发复杂的应用程序,并且应用逻辑只能按顺序执行,这也影响了系统的实时性能。
CPU运行时,其状态寄存器、程序执行位置寄存器PC(程序计数器寄存器)、堆栈位置寄存器SP(堆栈指针寄存器)以及一些通用寄存器和浮点寄存器构成了其执行快照,称为CPU上下文。 。如果我们能够保存CPU执行流的上下文,我们就可以利用上下文来恢复执行流。
基于此,操作系统开发者发明了软件并发机制——多线程。其原理是在系统中创建多个线程,每个线程都是一个独立的执行流,通过任务切换以分时的方式共享CPU。当当前线程在CPU上运行时,保存CPU上下文,这也是当前线程的上下文。它作为线程私有数据保存在线程中,然后将另一个线程的上下文恢复到CPU以恢复另一个线程的运行。 。这样当前线程将CPU转移给另一个线程,实现并发多线程操作。下图是线程1把CPU让给线程2的示意图:
有了多线程机制,编程模型发生了根本性的改变。应用程序可以分解为多个逻辑单元,每个逻辑单元由一个线程执行。同时可以创建一些系统后台任务,比如软件定时器任务,为应用程序提供一些系统服务。
多线程只是建立在软件级别的一个概念。底层CPU在某一时刻仍然只能执行一个线程。这就涉及到一个问题:哪个线程应该占用CPU?为了解决这个问题,引入了调度算法。物联网操作系统上一般采用基于优先级的时间片轮询调度算法。应用逻辑拆分成多个线程后,又涉及到另一个问题:多个线程之间如何协调?比如当两个线程想要同时访问一段内存数据时,如何保证数据的完整性。为了解决这个问题,引入了同步和互斥机制。此外,为了方便线程之间传输数据,还增加了通信机制。整个内核架构如下图所示:
CPU抽象层实现了CPU能力的抽象,主要包括CPU初始化、异常进入和退出、开关中断、Cache、MMU、任务初始上下文构建、任务上下文保存和恢复以及提供其他接口。它隐藏了不同架构的CPU之间在指令、寄存器、异常、浮点等方面的差异。基于这个抽象层,内核实现了线程、调度、同步互斥、通信等功能。上层应用程序通过内核提供的接口来使用CPU能力。
本质上,无论是哪种CPU架构,都是为了提供计算能力。因此,可以抽象出相同的接口。包括多核架构的CPU也可以抽象出与单核相同的接口,只不过多线程可以在多核处理器上同时运行。
基于线程模型的软件抽象无疑是成功的。它不仅隐藏了硬件实现的细节,还为硬件赋能:每个线程不仅仅是一个简单的执行流程,它还有生命周期和状态。例如,AliOS Things物联网操作系统支持五种线程状态:就绪、阻塞、睡眠、挂起和删除。应用程序可以更轻松地基于线程功能实现应用程序逻辑。 AliOS Things上的线程状态流程如下图所示:
嵌入式操作系统都采用类似的方法来抽象CPU能力,向上层提供统一的接口,有效解决了CPU碎片问题。一些嵌入式操作系统,例如FreeRTOS和uC/OS,主要提供CPU部分的抽象。
3. 外设和板级支持包(BSP)
在物联网系统中,外围设备受到碎片化的打击最严重。本部分将比较PC平台并分析物联网系统外围碎片化的原因和挑战。
3.1 PC平台外设及总线
PC还将连接各种各样的外围设备,例如不同性能的显卡和声卡、不同功能的打印机以及不同协议的通信设备。因此,PC上的桌面操作系统也会遇到碎片问题。然而,不同硬件配置的PC只需要安装相同的操作系统和最多几个额外的设备驱动程序。无需为他们定制操作系统。这是怎么做到的?
PC平台上的外设主要通过PCIE和USB总线连接。下面以PCIE总线为例进行说明。 PCIE总线拓扑图如下:
设备挂载在PCIE总线上,每条总线都有一个编号。总线上最多可以挂载 32 个设备,挂载位置编码为 0 到 31。每个设备最多可以有 8 个功能,编码为 0 到 7。总线可以通过 PCIE 桥扩展为新总线,所以整个PCIE总线系统是一个树形结构。
在系统初始化期间,将遍历总线来发现和识别设备类型。这个过程称为设备枚举。该操作使用深度搜索算法遍历整个总线,依次组合 Bus/Device/Function 三个数字,并尝试从总线位置读取供应商 ID。如果读取到的值为0xFFFF,则表示该位置没有设备。否则,该位置有一个设备。读取的值是设备的制造商编号。此外,可以从设备的配置头中读取设备编号Device ID。系统可以根据Vendor ID/Device ID判断设备类型并加载指定的驱动程序。
简而言之,PCIE总线具有寻找外设并判断外设类型的能力。基于此功能,操作系统可以动态加载适当的驱动程序。
3.2 虚拟文件系统(VFS)
基于设备总线构建的设备框架实现了外设的自动识别和驱动程序的自动加载,可以有效处理硬件平台外设碎片化带来的问题。但每个外设提供的能力不同,这会导致提供给上层应用的接口碎片化,如下图所示:
Linux上提出了“一切皆文件”的设计理念,虚拟文件系统(vfs)抽象的外围能力向上层提供统一的open、read、write、ioctl接口。 open接口用于打开设备并对应设备初始化,read接口对应设备的数据输入,write对应设备的数据输出,ioctl用于控制设备,如设置模式和读取设备状态。这样上层应用就可以使用统一的接口来访问不同的设备。
当然,设备毕竟不同,外设的功能细节其实都集中在ioctl函数中。该函数的原型设计如下:
int ioctl(int fd, int req, ...);
其中,fd是文件描述符,在调用open函数打开设备时返回。 req是操作的命令码,用于表示不同的操作请求。可变参数部分用于传递命令参数。为了方便多个参数的传递,通常会设计一个结构体。每个外设都需要根据自己的具体需要设计一套命令代码和相应的参数结构。对于更复杂的显卡,可能有数百个ioctl命令。
3.3 IoT系统上的外设和BSP
出于成本和功耗的考虑,物联网芯片通常将CPU和外设集成在一颗芯片上,即SOC(System-on-a-Chip)或MCU(Microcontroller Unit),而不同的芯片往往根据自身的特点集成不同的芯片。外围设备,并且这种集成没有统一的标准。用于集成外设的总线通常不具备设备枚举功能,无法读取设备寄存器来确定设备类型。因此,在物联网硬件上进行开发时,只能查阅芯片手册来了解芯片上有哪些外设。同时,芯片厂商在集成外设IP核时,已经给外设分配了一个IO地址。开发时查阅芯片手册获取地址,驱动程序使用该地址访问外设。
在此类硬件平台下,操作系统只能针对特定芯片进行定制。物联网操作系统的开发人员为解决这个问题付出了巨大的努力,以尽可能减少碎片。一种设计策略是电路板支持包 (BSP)。它是外设的抽象层,每个硬件平台都有一个抽象层。它为内核提供了统一的外设访问接口,并保证内核本身与特定硬件解耦。物联网操作系统为多种硬件平台提供BSP。应用程序开发人员可以根据自己的需要选择使用其中一种,然后重新编译操作系统映像。如下图:
然而,硬件平台并不详尽,为了更好地满足不同应用的需求,新型物联网芯片层出不穷。特别是,很多厂商往往会定制硬件来满足自己应用的需要,在芯片之外添加一些外设。这种情况下,需要根据BSP开发规范开发新的BSP来支持新的硬件。
从PC硬件解决外设碎片问题的经验来看,软硬件协同设计是一个更好的思路。 HaaS(硬件即服务)物联网设备云集成开发框架提出的硬件构建块就是这一思想在物联网系统中的实践。设计思路是基于量化收敛的硬件构建块,构建满足各种物联网应用需求的硬件。传统上,不同硬件的需求是通过软件组件化来满足的。 HaaS的硬件构建块是通过软硬件协同组件化来满足不同应用的需求,从而解决物联网的碎片化问题。如下图:
3.4 IoT操作系统上的设备接口
Linux桌面操作系统通过VFS层为应用程序提供统一的外设访问接口。一些物联网操作系统,例如RTThread,借鉴了Linux的思想,实现了简化版的VFS组件,它不仅用于访问文件系统,还可以访问外设。
除了支持VFS组件之外,AliOS Things还提供了另一个接口——HAL(硬件抽象层)。它根据每个外设的功能,为其设计了一套接口。所以HAL实际上是一组接口。其优点是简单直观、易于使用、易于连接、易于维护。但扩展性较差,当新的外设出现时,需要设计新的接口。同时,一些从Linux移植过来的应用程序希望以Linux的方式使用外设,但HAL无法满足他们。
虽然通过VFS可以统一外设接口,但在物联网设备上也会出现水土不服的情况。首先,对接设备的工作量比HAL接口要大,尤其是一些简单的物联网外设,比如GPIO,必须按照VFS规范进行封装。其次,使用起来不直观。例如,访问I2C设备时,需要指定从设备的地址。在这种情况下,您不能简单地使用读写接口直接访问它。
两种接口都有各自的优点和缺点。选择哪种界面取决于操作系统的整体设计和定位。当然,你也可以选择两者都支持,通过配置来选择。接下来我们看看组件和配置带来的碎片问题。
4. 组件和配置
物联网操作系统的特点之一就是可定制性强。通过组件配置,应用程序仅选择所需的组件。灵活配置,满足不同应用的需求也是解决碎片的一种方式。这是一个很好的想法,但在具体实施中也会遇到问题。
第一个是组件内部的碎片化。在为物联网设计第三方组件时,通常希望它们能够在更多平台上运行。主要考虑两类平台:(1)无操作系统,该类平台无需考虑多线程问题; (2)对于操作系统,这类平台上需要考虑多线程问题,因此依赖于操作系统提供的接口。该组件提供了目标操作系统需要实现的接口层。有些组件是基于标准接口开发的,例如Posix,或者用C++语言编写。如下图:
为了支持不同类型的物联网平台,第三方组件通常会提供灵活的配置,例如内存占用量、启用功能数量等,以适应更多场景。更大的灵活性意味着更多的可配置项。为了减少依赖性或者提高易用性和性能,一些组件还会实现一些基本功能,比如内存管理、验证算法,甚至C库。另外,每个组件可能有自己的调试信息输出方式、接口设计理念等,当所有这些不同设计的组件组合在一起时,操作系统整体变得不一致,功能冗余、配置方式不同、编码不同当然,我们可以努力本地化第三方组件,但这会阻碍以后的升级。
第二个是如何配置。一种方法是集中配置,在一个或几个头文件中使用宏配置。这种方法比较直观,但由于物联网系统中配置项较多,组件之间存在依赖关系(选择一个组件后,需要选择另一个组件)或互斥(选择一个组件后,不能选择其他组件)选择另一个组件)),这会让配置工作变得更加繁琐,用户很难配置出满足自己需求的配置集。这种方法只适用于小型物联网操作系统,FreeRTOS就采用了这种方法。
另一种方法是离散配置,将各个组件的配置信息放在组件内部。由于配置项分散在各个组件中,配置比较困难,所以有些系统会使用类似menuconfig的图形化配置工具。该方法可以帮助用户处理组件之间的依赖关系和互斥关系。即当用户选择一个组件时,会自动选择它所依赖的组件,而排除与其互斥的组件。但当配置项过多时,整个图形配置层面就会变得更加复杂,用户在配置时也会遇到困难。例如,要配置某个参数,如果不熟悉,可能会像走迷宫一样找不到位置。大多数物联网操作系统,如AliOS Things、RTThread、ARM Mbed等都采用这种离散配置方式。
如果配置方法处理不当,最终的结果就是配置了很多不必要的组件,失去了系统的可剪裁性。在Linux系统上,由于用户运行各种应用程序,因此内核需要支持完整的功能。然而,将所有模块加载到RAM中会导致内存浪费。为此,Linux开发了动态加载功能。一些组件作为模块存储在外部硬盘上,并在需要时加载到内存中。与静态配置相比,动态加载更加方便。然而,一些物联网系统的非易失性存储空间也非常紧张,甚至小于RAM,无法存储所有需要加载的组件。
发展方向之一是缩小应用领域,向垂直领域发展。这样,各种组件不再需要为不同类型的应用提供多种配置,还可以专门针对垂直领域的应用需求进行优化,不仅提高了易用性,还增加了性能。当然,更好的方式是构建平台能力,这就要求操作系统具有良好的组件“分离”和“组合”能力。它可以快速组装,同时保持组件的独立性。比如离散+集中式混合配置方式,离散配置方式生成集中式配置文件,是垂直解决方案。它不仅简化了配置,还实现了配置重用。如下图:
5. 接口与框架
物联网操作系统的接口主要包括两类。一是面向应用开发者的API,代表操作系统向用户提供的能力;二是BSP开发者的平台对接接口,代表操作系统所依赖的能力。硬件能力。在物联网领域,应用程序开发人员和BSP开发人员很可能是同一个人。
IoT 操作系统通常提供一组本机 C 接口。使用原生接口的好处是性能高、资源占用低,这对于那些资源有限的平台是有利的。但它并不是通用的标准接口,增加了应用开发者的学习成本和移植成本。当从其他系统移植应用程序时,需要修改应用程序调用的系统接口。由于系统差异,移植的工作量也有所不同。例如,如果遇到语义不一样的接口,则需要调整应用程序代码或添加新接口。如果两个系统的任务优先级值的定义不同,则需要调整应用程序中的每个任务。优先事项。
Linux系统上的应用程序是基于Posix接口开发的,Posix接口是一组标准接口。一些应用程序开发人员希望只维护一种代码,既可以在Linux系统上运行,也可以在物联网系统上运行。为了方便这些开发人员,物联网操作系统,例如AliOS Things,提供了Posix接口支持,这大大减少了将Linux应用程序移植到物联网操作系统的工作量。代价是增加了 Posix 层的开销。
物联网应用正朝着更加智能化的方向发展。一些人工智能组件,例如语音识别、手势识别和图形引擎,通常是用C++语言开发的。因此,物联网操作系统需要支持C++语言。一个特例是ARM Mbed物联网操作系统,它用C++封装了整个系统。
为了方便不熟悉C语言的开发者开发物联网应用,HaaS物联网设备云集成开发框架提供了对JS和Python语言的支持。
原生接口满足小内存占用需求,Posix接口满足复杂应用需求,C++语言及其库提供的接口满足面向对象开发需求,JS、Python满足轻量级开发需求。四五套接口看起来很碎片化,有一种用碎片来对付碎片的感觉。但我认为判断软件碎片的标准应该是:需要增加或调整的代码量(包括配置项的数量)以满足不同应用的需求。这四五套接口就可以满足大部分应用的需求,而且不需要因为应用的变化而增加接口或者调整接口,所以我认为这部分的碎片化程度较低。
BSP开发人员通过实现硬件对接接口,将物联网操作系统移植到目标平台。这个socket的设计决定了物联网操作系统支持新平台的工作量,因此也影响了物联网操作系统的可用性。关键因素之一。
我将三个物联网操作系统FreeRTOS、RTThread和ARM Mbed移植到同一个开发板上,并运行了性能测试用例。花费时间最少的进程是FreeRTOS,花费时间最多的是ARM Mbed。两个系统的区别在于,ARM Mbed的硬件对接接口背后有一套极其完整、复杂的框架。如果想要适应一个新的平台,就需要对这个框架的使用有一定的了解,而这个过程需要花费大量的时间。 FreeRTOS没有设备框架,内核直接调用硬件对接接口。可见,硬件对接接口背后的框架是一把双刃剑。用得好,就会成为助力,用得不好,就会成为阻碍。需要具备以下三个特点:(1)抽象外设功能,集成常用操作,减少对接工作量; (2)具有良好的扩展性; (3)边际使用成本低。虽然需要时间,但后续使用可以节省很多时间。
如果没有上述特性,硬件对接接口背后的框架将成为一场灾难。想要添加新功能的用户不知道从哪里开始。如果想要了解其背后的机制,就需要了解一整套框架,这大大增加了学习、维护和使用的成本。同时,在外设碎片化需求的冲击下,框架本身逐渐解体,变得越来越碎片化。
六、总结
与硬件相比,软件最大的优势就是边际成本低,甚至可以接近于零。但是,分裂问题将大大增加物联网操作系统的重用成本,并防止物联网操作系统成为通用的设备端软件平台。如果处理不当,则不仅会损失低边缘成本的优势,而且甚至会将其变成具有高边缘成本的软件怪兽。例如,针对特定平台的一些特殊处理将成为其在其他平台上应用的障碍。
在开发IoT操作系统时,您将面临多个决策维度,包括性能,功能,易用性,实时,资源使用量等。根据不同的设计决策,制定的代码差异很大。因此,重要的是要确保开发基于相同的设计决策,以便整个操作系统都有良好的一致性。此外,文档是解决破碎问题的重要辅助手段。
生活日报网·版权声明
本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。本站部分作品是由网友自主投稿和发布、编辑整理上传,对此类作品本站仅提供交流平台,不为其版权负责。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。
本网站所提供的信息,只供参考之用。本网站不保证信息的准确性、有效性、及时性和完整性。本网站及其雇员一概毋须以任何方式就任何信息传递或传送的失误、不准确或错误,对用户或任何其他人士负任何直接或间接责任。在法律允许的范围内,本网站在此声明,不承担用户或任何人士就使用或未能使用本网站所提供的信息或任何链接所引致的任何直接、间接、附带、从属、特殊、惩罚性或惩戒性的损害赔偿。
【特别提醒】:如您不希望作品出现在本站,可联系我们要求撤下您的作品。邮箱 sunny@sdlife.com.cn





