1:前言
由于在项目中有所接触到相关的多核调度以及共享内存、核间通信等方面的知识,因此本篇笔记用来记录项目调试过程中所遇到一些问题与思考。
本篇笔记是通过学习
1:《ARM® Generic Interrupt Controller Architecture Specification - GIC architecture version 3.0 and version 4.0》
2:嵌入式中的多核开发和核间通信总结_核间通讯-CSDN博客
3:[笔记] GICv3/v4 ITS 与 LPI_gic lpi-CSDN博客
所做的笔记
2:共享内存
2.1基本定义
共享内存是一种高效的进程间通信(IPC)机制,允许多个进程直接访问同一块物理内存区域。通过共享内存,多个进程可以在内存中共享数据,而无需通过内核进行中转,从而避免了数据复制和系统调用的开销。这种机制使得数据在多个进程之间能够快速传递,是进程间通信中速度最快的方式。
2.2 工作原理
共享内存的工作原理基于操作系统的内存管理机制。具体步骤如下:
-
创建共享内存:操作系统在物理内存中分配一个共享内存段。
-
映射共享内存:各个进程通过特定的标识符访问同一块共享内存空间,并将其映射到自己的虚拟地址空间。
-
数据访问:进程可以直接对映射后的内存区域进行读写操作,其他进程能够即时看到这些改动。
-
销毁共享内存:当共享内存不再需要时,进程会解除映射并销毁共享内存
3:核间通信(IPC)
3.1基础定义
核间通信(Inter-Processor Communication,IPC)是指在多核系统中,不同处理器核心之间进行数据传递和同步的机制。其目的是为了在多核架构中实现高效的合作与资源共享,使各个核心能够协同完成复杂的任务。
3.2数据一致性
在核间通信中一般使用下列方法进行数据一致性的保证:
1. 使用锁机制
锁是确保数据一致性最常用的方法之一。在多核系统中,锁可以防止多个核心同时访问共享数据,从而避免数据竞争。
互斥锁(Mutex):互斥锁可以确保同一时间只有一个核心可以访问共享数据。在访问共享数据之前,核心需要获取锁,访问完成后释放锁。
自旋锁(Spinlock):自旋锁是一种忙等待锁,适用于短时间的锁定操作。在多核系统中,自旋锁可以快速保护共享数据,防止多个核心同时写入。
读写锁(Read-Write Locks):如果共享数据的读操作远多于写操作,使用读写锁可以提高效率。读写锁允许多个读操作同时进行,但写操作需要独占。
2. 内存屏障
内存屏障(Memory Barrier)是一种同步机制,用于确保内存操作的顺序性,防止编译器和处理器对内存操作进行重排序。
编译器屏障:防止编译器对代码进行优化重排序。
CPU内存屏障:防止CPU对内存操作进行乱序执行。
3. 使用共享内存保护机制
在使用共享内存进行核间通信时,必须采取措施保护共享内存中的数据。
关闭全局中断:在访问共享内存时,通过关闭全局中断来防止其他核心的中断处理程序访问共享数据。
使用自旋锁保护共享内存:在访问共享内存时,使用自旋锁来保护数据,确保同一时间只有一个核心可以访问。
4:多核调度
在不同的实时操作系统(RTOS)中,提供的底层接口可能无法完全满足项目需求。例如,你可能需要同时调度核0到核3的GICD_ISENABLER
寄存器,但现有的底层接口可能仅支持使能当前核的GICD_ISENABLER
寄存器。在这种情况下,为了满足需求,就需要对底层接口进行改写和优化,以实现对多个核的寄存器操作。
下面分享一个代码思路
#include <stdint.h>
#include <stdio.h>
//根据芯片手册决定base地址以及不同核之间寄存器间隔为多少
#define GICD_BASE 0x10000000
#define GICD_ISENABLER_OFFSET 0x100
#define Register_Interval_Address 0x1000
// 定义一个函数来使能指定中断号的中断
void enable_interrupt(uint32_t core_num, uint32_t interrupt_id, uint32_t core_mask) {
uint32_t* gicd_isenabler = (uint32_t*)(GICD_BASE + GICD_ISENABLER_OFFSET);
// 遍历所有核心,使能指定的中断
for (uint32_t core_id = 0; core_id < core_num; core_id++) {
if (core_mask & (1 << core_id)) {
// 计算当前核心的 GICD_ISENABLER 寄存器地址
uint32_t* core_isenabler = gicd_isenabler + (core_id * Register_Interval_Address );
// 使能指定的中断
*core_isenabler |= (1 << interrupt_id);
printf("Core %d: Interrupt %d enabled\n", core_id, interrupt_id);
}
}
}
int main() {
//假设一共有4个核
uint32_t core_mask = 0b1111;
// 使能中断号为5的中断
enable_interrupt(4, 5, core_mask);
return 0;
}