多核RTOS:AMP与SMP架构在嵌入式中的选择——核间通信与负载均衡
文章目录

每日一句正能量
真正的善,是先对自己慈悲,再对世界温柔。
对外人极尽温柔,对自己冷酷刻薄。结果要么耗竭,要么委屈。对自己慈悲≠自私,而是先填满自己的能量池,溢出来的部分,才是健康可循环的温柔。否则,温柔会变成交换、牺牲或道德绑架。
一、引言:多核时代的嵌入式挑战
随着半导体工艺的发展,嵌入式处理器已从单核时代迈入多核时代。从NXP i.MX7(Cortex-A7 + Cortex-M4)、Xilinx Zynq MPSoC(Cortex-A53 + Cortex-R5)到STM32MP1(Cortex-A7 + Cortex-M4),异构多核SoC已成为工业控制、汽车电子、通信设备等领域的主流选择。
然而,多核架构给嵌入式开发者带来了新的技术挑战:
- 架构选择困境:面对AMP(非对称多处理)和SMP(对称多处理)两种架构,如何根据应用场景做出正确选择?
- 核间通信复杂度:不同核心运行不同操作系统时,如何实现高效、可靠的数据交换?
- 负载均衡难题:在SMP架构下,如何让多个核心协同工作,避免"一核有难、多核围观"的局面?
本文将深入剖析AMP与SMP的技术原理、核间通信机制和负载均衡策略,帮助开发者在实际项目中做出最优架构决策。
二、AMP与SMP架构对比
2.1 架构定义与核心差异

AMP(Asymmetric Multiprocessing,非对称多处理):
- 每个核心运行独立的操作系统实例(如Core 0运行Linux,Core 1运行FreeRTOS)
- 各核心拥有独立的内存空间,通过共享内存区域进行通信
- 核心之间是主从关系或对等关系,各自承担不同角色
- 典型应用:工业网关、汽车ECU、通信基站
SMP(Symmetric Multiprocessing,对称多处理):
- 所有核心运行同一个操作系统实例(如FreeRTOS SMP)
- 所有核心共享统一的内存地址空间
- 核心之间是完全对等关系,由全局调度器统一调度
- 典型应用:高吞吐网络处理、并行信号处理、通用多任务系统
2.2 关键特性对比
| 维度 | AMP | SMP |
|---|---|---|
| OS支持 | 每个核心可运行不同OS | 所有核心运行同一OS |
| 内存模型 | 独立内存 + 共享内存区域 | 统一共享内存 |
| 调度方式 | 各OS独立调度 | 全局统一调度 |
| 实时性 | 强(实时核不受干扰) | 中(需考虑调度开销) |
| 开发复杂度 | 高(需处理核间通信) | 低(类似单核开发) |
| 适用场景 | 异构系统、实时+非实时 | 同构系统、高并行计算 |
三、核间通信(IPC)机制详解
3.1 核间通信架构
在AMP架构中,核间通信是系统的核心挑战。以Linux + FreeRTOS的典型配置为例:

核间通信的核心组件:
- 共享内存(Shared Memory):作为数据传输的物理载体
- 软件中断(SGI/IPI):用于通知对方核心有新数据到达
- 内存屏障(DMB/DSB):确保缓存一致性
3.2 OpenAMP框架
OpenAMP(Open Asymmetric Multi-Processing)是目前最主流的AMP核间通信框架,它提供了标准化的生命周期管理(LCM)和进程间通信(IPC)能力。
OpenAMP三大核心组件:
| 组件 | 功能 | 对应Linux子系统 |
|---|---|---|
| RemoteProc | 远程处理器生命周期管理(启动/停止/加载固件) | Linux remoteproc |
| RPMsg | 基于消息的核心间通信 | Linux rpmsg |
| VirtIO | 虚拟设备抽象层,管理共享内存和vring | Linux virtio |
RPMsg消息格式:
+------------------+------------------+------------------+
| src (32bit) | dst (32bit) | reserved |
| (源端点地址) | (目标端点地址) | (保留对齐) |
+------------------+------------------+------------------+
| len (16bit) | flags (16bit) | Payload... |
| (数据长度) | (标志位) | (用户数据) |
+------------------+------------------+------------------+
3.3 核间通信代码实战
以下是在STM32MP1平台上,基于OpenAMP实现Linux(Cortex-A7)与FreeRTOS(Cortex-M4)核间通信的完整示例:
/* ============================================
* AMP核间通信示例 - FreeRTOS侧 (Cortex-M4)
* 平台: STM32MP1
* 框架: OpenAMP + RPMsg
* ============================================ */
#include "openamp.h"
#include "rpmsg.h"
#include "FreeRTOS.h"
#include "task.h"
/* 共享内存配置 (由设备树定义) */
#define RPMSG_SHARED_MEMORY_BASE 0x10040000
#define RPMSG_SHARED_MEMORY_SIZE 0x40000 /* 256KB */
/* RPMsg端点配置 */
#define RPMSG_SERVICE_NAME "rpmsg-sensor"
#define RPMSG_ENDPOINT_ADDR 0x401 /* 本地端点地址 */
/* 消息结构体 */
typedef struct {
uint32_t sensor_id;
float temperature;
float humidity;
uint32_t timestamp;
} SensorData_t;
/* RPMsg端点实例 */
static struct rpmsg_endpoint lept;
static volatile uint8_t g_rpmsg_ready = 0;
/* ==========================================
* RPMsg接收回调函数
* 当Linux端发送消息时触发
* ========================================== */
static int rpmsg_recv_callback(struct rpmsg_endpoint *ept, void *data,
size_t len, uint32_t src, void *priv)
{
(void)ept;
(void)src;
(void)priv;
/* 解析接收到的控制命令 */
if (len >= sizeof(uint32_t)) {
uint32_t cmd = *(uint32_t *)data;
switch (cmd) {
case 0x01: /* 启动传感器采集 */
vTaskResume(xSensorTaskHandle);
break;
case 0x02: /* 停止传感器采集 */
vTaskSuspend(xSensorTaskHandle);
break;
case 0x03: /* 配置采样率 */
if (len >= sizeof(uint32_t) * 2) {
uint32_t rate = ((uint32_t *)data)[1];
vSetSampleRate(rate);
}
break;
default:
break;
}
}
return RPMSG_SUCCESS;
}
/* ==========================================
* OpenAMP初始化
* ========================================== */
static void vOpenAMPInit(void)
{
/* 1. 初始化libmetal (硬件抽象层) */
struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
metal_init(&metal_params);
/* 2. 初始化RemoteProc资源 */
struct remoteproc rproc;
struct remoteproc_ops rproc_ops = {
.init = NULL,
.remove = NULL,
.start = NULL,
.stop = NULL,
};
remoteproc_init(&rproc, &rproc_ops, NULL, NULL, NULL, NULL);
/* 3. 创建VirtIO设备 */
struct virtio_device vdev;
/* ... 配置VirtIO设备和vring ... */
/* 4. 初始化RPMsg */
rpmsg_init_vdev(&rvdev, &vdev, NULL, NULL, NULL);
/* 5. 创建RPMsg端点 */
rpmsg_create_ept(&lept, RPMSG_SERVICE_NAME, RPMSG_ENDPOINT_ADDR,
RPMSG_ADDR_ANY, rpmsg_recv_callback, NULL);
g_rpmsg_ready = 1;
}
/* ==========================================
* 传感器数据采集任务
* 通过RPMsg向Linux端发送数据
* ========================================== */
static void vSensorTask(void *pvParameters)
{
SensorData_t sensorData;
uint32_t seqNum = 0;
(void)pvParameters;
/* 等待RPMsg就绪 */
while (!g_rpmsg_ready) {
vTaskDelay(pdMS_TO_TICKS(10));
}
for (;;) {
/* 读取传感器数据 */
sensorData.sensor_id = 0x01;
sensorData.temperature = fReadTemperature();
sensorData.humidity = fReadHumidity();
sensorData.timestamp = xTaskGetTickCount();
/* 通过RPMsg发送数据到Linux端 */
/* 使用非阻塞发送,避免影响实时性 */
int ret = rpmsg_send(&lept, &sensorData, sizeof(SensorData_t));
if (ret < 0) {
/* 发送失败处理 - 缓冲区满 */
/* 可选择丢弃或重试 */
}
seqNum++;
vTaskDelay(pdMS_TO_TICKS(100)); /* 100ms采样周期 */
}
}
/* ==========================================
* 主函数入口
* ========================================== */
int main(void)
{
/* 硬件初始化 */
HAL_Init();
SystemClock_Config();
/* 初始化OpenAMP */
vOpenAMPInit();
/* 创建传感器任务 */
xTaskCreate(vSensorTask, "SensorTask", 512, NULL,
configMAX_PRIORITIES - 1, &xSensorTaskHandle);
/* 启动调度器 */
vTaskStartScheduler();
/* 不会到达这里 */
for (;;);
}
Linux侧(Cortex-A7)用户空间代码:
/* ============================================
* Linux侧 RPMsg通信示例
* 通过rpmsg_char设备与Cortex-M4通信
* ============================================ */
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define RPMSG_DEVICE "/dev/rpmsg0"
#define CMD_START 0x01
#define CMD_STOP 0x02
#define CMD_SET_RATE 0x03
typedef struct {
uint32_t sensor_id;
float temperature;
float humidity;
uint32_t timestamp;
} SensorData_t;
int main(void)
{
int fd = open(RPMSG_DEVICE, O_RDWR);
if (fd < 0) {
perror("Failed to open rpmsg device");
return -1;
}
/* 发送启动命令 */
uint32_t startCmd = CMD_START;
write(fd, &startCmd, sizeof(startCmd));
/* 设置采样率为50ms */
uint32_t rateCmd[2] = {CMD_SET_RATE, 50};
write(fd, &rateCmd, sizeof(rateCmd));
/* 接收传感器数据 */
SensorData_t data;
while (1) {
ssize_t len = read(fd, &data, sizeof(SensorData_t));
if (len == sizeof(SensorData_t)) {
printf("Sensor[%lu]: Temp=%.2f°C, Humid=%.2f%%, TS=%lu\n",
data.sensor_id, data.temperature,
data.humidity, data.timestamp);
}
}
close(fd);
return 0;
}
四、SMP架构负载均衡机制
4.1 SMP调度架构
FreeRTOS从V11.0.0版本开始,将SMP支持合并到主线内核中,实现了真正的对称多处理。

SMP调度的核心特点:
- 单一内核映像:所有核心运行同一个FreeRTOS内核
- 全局任务队列:所有就绪任务共享同一个队列
- 自动负载均衡:调度器自动将任务分配到负载最轻的核心
- 处理器亲和性:支持将任务绑定到特定核心(CPU Affinity)
4.2 负载均衡策略
| 策略 | 描述 | 优点 | 缺点 |
|---|---|---|---|
| 全局队列调度 | 所有核心共享一个全局就绪队列 | 负载最均衡 | 队列竞争开销大 |
| 分区调度 | 每个核心维护独立的就绪队列 | 无队列竞争 | 负载可能不均衡 |
| 混合调度 | 高优先级任务全局调度,低优先级分区 | 兼顾均衡与性能 | 实现复杂 |
| 任务窃取 | 空闲核心从忙碌核心"窃取"任务 | 自适应负载均衡 | 缓存局部性损失 |
4.3 SMP代码配置示例
/* ============================================
* FreeRTOS SMP配置与任务亲和性示例
* 平台: ESP32 / STM32H7 / 其他多核MCU
* ============================================ */
#include "FreeRTOS.h"
#include "task.h"
/* SMP相关配置 (FreeRTOSConfig.h) */
#define configNUMBER_OF_CORES 2 /* 核心数量 */
#define configUSE_CORE_AFFINITY 1 /* 启用CPU亲和性 */
#define configUSE_TASK_PREEMPTION 1 /* 启用抢占 */
#define configUSE_TIME_SLICING 1 /* 启用时间片轮转 */
/* 任务亲和性掩码 */
#define NO_AFFINITY tskNO_AFFINITY
#define CORE_0_ONLY (1 << 0)
#define CORE_1_ONLY (1 << 1)
#define BOTH_CORES ((1 << 0) | (1 << 1))
/* ==========================================
* 创建绑定到特定核心的任务
* ========================================== */
void vCreateAffinityTasks(void)
{
/* 网络处理任务 - 绑定到Core 0 */
/* 原因: 网络中断在Core 0上处理,避免缓存失效 */
xTaskCreateAffinitySet(
vNetworkTask, /* 任务函数 */
"NetworkTask", /* 任务名称 */
4096, /* 栈大小 */
NULL, /* 参数 */
configMAX_PRIORITIES - 2, /* 高优先级 */
CORE_0_ONLY, /* 仅运行在Core 0 */
&xNetworkTaskHandle /* 任务句柄 */
);
/* 电机控制任务 - 绑定到Core 1 */
/* 原因: 需要确定性实时响应,避免被其他任务干扰 */
xTaskCreateAffinitySet(
vMotorControlTask,
"MotorControl",
2048,
NULL,
configMAX_PRIORITIES - 1, /* 最高优先级 */
CORE_1_ONLY, /* 仅运行在Core 1 */
&xMotorTaskHandle
);
/* 日志记录任务 - 可在任意核心运行 */
/* 原因: 非关键任务,由调度器自动负载均衡 */
xTaskCreateAffinitySet(
vLoggingTask,
"LoggingTask",
2048,
NULL,
2, /* 低优先级 */
BOTH_CORES, /* 可在任意核心运行 */
&xLoggingTaskHandle
);
/* 数据处理任务 - 无亲和性,自动负载均衡 */
xTaskCreateAffinitySet(
vDataProcessingTask,
"DataProc",
4096,
NULL,
5, /* 中优先级 */
NO_AFFINITY, /* 无亲和性,调度器自动分配 */
&xDataTaskHandle
);
}
/* ==========================================
* 运行时动态调整任务亲和性
* ========================================== */
void vAdjustTaskAffinity(void)
{
/* 场景: 系统负载变化时动态调整 */
/* 获取当前各核心负载 */
UBaseType_t uxCore0Load = uxTaskGetCoreLoad(0);
UBaseType_t uxCore1Load = uxTaskGetCoreLoad(1);
/* 如果Core 0负载过高,将非关键任务迁移到Core 1 */
if (uxCore0Load > 80 && uxCore1Load < 50) {
vTaskCoreAffinitySet(xLoggingTaskHandle, CORE_1_ONLY);
}
/* 如果Core 1负载过高,将非关键任务迁移到Core 0 */
if (uxCore1Load > 80 && uxCore0Load < 50) {
vTaskCoreAffinitySet(xLoggingTaskHandle, CORE_0_ONLY);
}
}
/* ==========================================
* 中断亲和性配置
* 将特定中断绑定到特定核心处理
* ========================================== */
void vConfigureInterruptAffinity(void)
{
/* 将ETH中断绑定到Core 0 */
/* 确保网络数据包始终在同一核心处理,提高缓存命中率 */
vPortSetInterruptAffinity(ETH_IRQn, CORE_0_ONLY);
/* 将电机编码器中断绑定到Core 1 */
/* 确保电机控制中断不被网络流量延迟 */
vPortSetInterruptAffinity(ENCODER_IRQn, CORE_1_ONLY);
/* 将定时器中断分发到两个核心 */
vPortSetInterruptAffinity(TIM_IRQn, BOTH_CORES);
}
4.4 SMP中的同步原语
在SMP架构中,多个核心可能同时访问共享资源,需要特殊的同步机制:
/* ==========================================
* SMP环境下的自旋锁 (Spinlock)
* 用于保护极短临界区,避免任务切换开销
* ========================================== */
static portMUX_TYPE xSpinLock = portMUX_INITIALIZER_UNLOCKED;
void vCriticalSectionExample(void)
{
/* 获取自旋锁 - 阻塞其他核心进入 */
taskENTER_CRITICAL(&xSpinLock);
/* 临界区代码 - 访问共享资源 */
gSharedCounter++;
gSharedData[index] = value;
/* 释放自旋锁 */
taskEXIT_CRITICAL(&xSpinLock);
}
/* ==========================================
* SMP环境下的递归互斥锁
* 用于保护较长临界区,允许同一任务递归获取
* ========================================== */
static SemaphoreHandle_t xRecursiveMutex = NULL;
void vMutexInit(void)
{
xRecursiveMutex = xSemaphoreCreateRecursiveMutex();
}
void vProtectedFunction(void)
{
if (xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) {
/* 访问共享资源 */
vUpdateSharedResource();
/* 递归调用另一需要同一锁的函数 */
vAnotherProtectedFunction();
xSemaphoreGiveRecursive(xRecursiveMutex);
}
}
五、缓存一致性与内存屏障
5.1 多核缓存一致性挑战
在多核系统中,每个核心拥有独立的L1 Cache。当多个核心访问同一内存地址时,可能出现缓存不一致的问题:

典型问题场景:
- Core 0写入数据到共享内存,但数据仅存在于Core 0的Cache中(Modified状态)
- Core 1读取同一地址,如果直接从自己的Cache读取,会得到旧值
- 需要通过缓存一致性协议(MESI)和内存屏障指令确保数据一致性
5.2 ARM内存屏障指令
/* ==========================================
* ARM Cortex-M/R/A 内存屏障指令详解
* ========================================== */
/* DMB - Data Memory Barrier
* 确保屏障前的所有内存访问完成后再执行屏障后的内存访问
* 使用场景: 核间数据同步、DMA操作 */
#define DMB() __asm volatile ("dmb" ::: "memory")
/* DSB - Data Synchronization Barrier
* 确保所有缓存、TLB、分支预测操作完成
* 使用场景: 上下文切换、系统状态变更 */
#define DSB() __asm volatile ("dsb" ::: "memory")
/* ISB - Instruction Synchronization Barrier
* 刷新流水线,确保后续指令重新从内存获取
* 使用场景: 代码动态修改、MPU配置变更 */
#define ISB() __asm volatile ("isb" ::: "memory")
/* ==========================================
* 核间通信中的内存屏障使用示例
* ========================================== */
/* 共享内存结构体 */
typedef struct {
volatile uint32_t flag; /* 数据就绪标志 */
volatile uint32_t data; /* 共享数据 */
volatile uint32_t seq; /* 序列号 */
} SharedMem_t;
/* Core 0 写入数据 */
void vCore0WriteData(SharedMem_t *shm, uint32_t value)
{
/* 1. 写入数据 */
shm->data = value;
shm->seq++;
/* 2. 数据内存屏障 - 确保数据写入完成 */
DMB();
/* 3. 设置标志 - 通知Core 1数据就绪 */
shm->flag = 1;
/* 4. 触发软件中断通知Core 1 */
vTriggerSGI(1, 1); /* 向Core 1发送SGI中断 */
}
/* Core 1 读取数据 */
uint32_t vCore1ReadData(SharedMem_t *shm)
{
uint32_t value;
/* 等待标志被设置 (在中断处理中检查) */
while (shm->flag == 0) {
/* 等待或休眠 */
__WFE(); /* 等待事件 */
}
/* 数据同步屏障 - 确保看到最新的数据 */
DSB();
/* 读取数据 */
value = shm->data;
/* 清除标志 */
shm->flag = 0;
DMB(); /* 确保标志清除被其他核心看到 */
return value;
}
六、典型应用场景分析
6.1 AMP场景:工业智能网关

场景描述:工业智能网关需要同时处理复杂的网络协议(Linux侧)和实时的电机控制(FreeRTOS侧)。
架构选择:AMP
| 核心 | 操作系统 | 职责 | 实时性要求 |
|---|---|---|---|
| Core 0 | Linux | Web服务器、数据库、网络协议栈、文件系统 | 软实时 |
| Core 1 | FreeRTOS | 电机PID控制、传感器采集、安全监控、紧急停止 | 硬实时 |
核间通信:通过RPMsg实现传感器数据上报和控制命令下发,延迟<1ms。
优势:
- 实时核不受Linux调度抖动影响,保证电机控制确定性
- Linux提供丰富的网络协议和文件系统支持
- 两个域独立开发、独立升级,降低耦合度
6.2 SMP场景:高吞吐网络处理器
场景描述:网络数据包处理需要高吞吐量,单个核心无法满足100Mbps+的处理需求。
架构选择:SMP
任务分配:
- Core 0:网络数据包接收(中断处理)、协议解析
- Core 1:数据包转发、加密/解密、QoS处理
- 负载均衡:高优先级数据包处理任务可在任意核心运行,调度器自动分配
优势:
- 统一代码库,开发维护简单
- 自动负载均衡,充分利用多核性能
- 任务可在核心间迁移,提高系统弹性
七、架构选择决策树

决策流程:
-
是否需要运行不同OS?(如Linux + RTOS)
- 是 → 选择 AMP
- 否 → 继续下一步
-
所有核心是否运行同一RTOS?
- 是 → 选择 SMP
- 否 → 考虑虚拟化或Hypervisor方案
关键决策因素:
| 因素 | 推荐AMP | 推荐SMP |
|---|---|---|
| 需要运行Linux + RTOS | ✅ | ❌ |
| 需要强实时隔离 | ✅ | ❌ |
| 核心同构(相同架构) | ❌ | ✅ |
| 需要自动负载均衡 | ❌ | ✅ |
| 开发资源有限 | ❌ | ✅ |
| 需要独立域升级 | ✅ | ❌ |
| 高并行计算需求 | ❌ | ✅ |
八、常见问题与最佳实践
8.1 AMP常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 核间通信延迟高 | 频繁使用中断通知 | 采用批量传输 + 环形缓冲区 |
| 共享内存数据损坏 | 缺少内存屏障 | 在关键位置插入DMB/DSB |
| RPMsg通道建立失败 | 资源表配置错误 | 检查设备树和resource_table |
| 实时核被Linux干扰 | 共享外设冲突 | 通过设备树明确划分外设归属 |
8.2 SMP常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 任务在核心间频繁迁移 | 缺少CPU亲和性设置 | 为关键任务设置xTaskCoreAffinitySet |
| 自旋锁导致死锁 | 中断上下文获取锁 | 使用taskENTER_CRITICAL_FROM_ISR |
| 缓存伪共享 | 多个核心访问同一缓存行 | 按缓存行对齐(64字节)分离数据 |
| 负载不均衡 | 任务优先级设计不当 | 使用混合调度策略 |
8.3 性能优化建议
/* ==========================================
* SMP性能优化: 避免缓存伪共享
* ========================================== */
/* 错误示例 - 多个核心频繁修改同一缓存行 */
struct BadLayout {
uint32_t core0_counter; /* Core 0修改 */
uint32_t core1_counter; /* Core 1修改 - 同一缓存行! */
uint32_t core2_counter; /* Core 2修改 - 同一缓存行! */
};
/* 正确示例 - 按缓存行对齐分离 */
struct __attribute__((aligned(64))) GoodLayout {
uint32_t counter;
uint8_t padding[60]; /* 填充至64字节缓存行 */
};
struct GoodLayout gCoreCounters[3]; /* 每个核心独立缓存行 */
/* ==========================================
* AMP性能优化: 批量传输减少中断
* ========================================== */
/* 批量发送传感器数据,减少RPMsg中断频率 */
#define BATCH_SIZE 16
void vBatchSendSensorData(void)
{
static SensorData_t batchBuffer[BATCH_SIZE];
static uint8_t batchIndex = 0;
/* 采集数据到批量缓冲区 */
batchBuffer[batchIndex].temperature = fReadTemp();
batchBuffer[batchIndex].humidity = fReadHumidity();
batchIndex++;
/* 批量发送 */
if (batchIndex >= BATCH_SIZE) {
rpmsg_send(&lept, batchBuffer, sizeof(SensorData_t) * BATCH_SIZE);
batchIndex = 0;
}
}
九、总结与展望
AMP与SMP代表了嵌入式多核系统的两种截然不同的设计哲学:
AMP强调隔离与异构,通过让不同核心运行最适合其角色的操作系统,实现功能与实时性的最佳平衡。OpenAMP框架的标准化使得Linux + RTOS的异构组合成为工业界的成熟方案。
SMP强调统一与对称,通过单一操作系统映像和全局调度器,实现开发简化与自动负载均衡。FreeRTOS SMP的成熟让嵌入式开发者也能享受到多核并行处理的便利。
在实际项目中,选择AMP还是SMP取决于以下核心问题:你的系统是否需要同时运行不同操作系统?是否需要强实时隔离?
随着RISC-V多核架构的兴起和ARM Cortex-X系列性能核心的普及,嵌入式多核系统将继续向更高性能、更低功耗的方向发展。无论选择AMP还是SMP,掌握核间通信机制和负载均衡策略,都是每一位嵌入式开发者必备的核心技能。
转载自:https://blog.csdn.net/u014727709/article/details/162508769
欢迎 👍点赞✍评论⭐收藏,欢迎指正
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)