IPC
(Inter-Process Communication)与RPC
(Remote Procedure Call)用于实现跨进程通信,不同的是前者使用 Binder 驱动,用于设备内的跨进程通信,后者使用软总线驱动,用于跨设备跨进程通信。
在分析鸿蒙的进程间通信首先我们先了解一下进程间通信的方式
匿名管道
匿名管道是一种半双工的通信方式,它可以在两个进程之间传递数据。匿名管道的特点是数据只能单向流动,而且通常只用于具有亲缘关系的进程之间进行通信,例如父子进程之间命名管道
命名管道与管道类似,但是它可以在不具有亲缘关系的进程之间进行通信。与管道不同的是,命名管道具有一个唯一的名称,可以在文件系统中进行访问信号
信号是一种异步通信方式,它允许一个进程向另一个进程发送一个信号。信号通常用于处理异步事件,例如键盘中断、终端关闭等共享内存
共享内存是一种高效的进程通信方式,它允许多个进程访问同一块物理内存,从而实现数据共享。共享内存的优点是速度快,但是需要处理并发访问和同步问题信号量
信号量是一种进程间同步和互斥的机制,它可以用于控制进程对共享资源的访问。信号量通常用于进程之间的同步和互斥,例如保护共享内存中的数据套接字
套接字是一种进程间通信方式,它可以在不同的计算机之间进行通信。套接字通常用于实现分布式系统和网络通信消息队列
消息队列是一种进程间通信方式,它允许进程之间传递消息。消息队列通常用于进程之间传递结构化的数据,例如进程之间传递命令和数据等
实现原理
IPC 和 RPC 通常采用客户端-服务器(Client-Server)模型,在使用时,请求服务的(Client)一端进程可获取提供服务(Server)一端所在进程的代理(Proxy),并通过此代理读写数据来实现进程间的数据通信,更具体的讲,首先请求服务的(Client)一端会建立一个服务提供端(Server)的代理对象,这个代理对象具备和服务提供端(Server)一样的功能,若想访问服务提供端(Server)中的某一个方法
鸿蒙 IPC 进程间通信机制
鸿蒙 IPC 进程间通信机制是鸿蒙操作系统中用于进程间通信的基础设施,它提供了多种通信方式,包括消息队列、共享内存和远程过程调用等。这些通信方式可根据不同的场景和需求来选择和使用,以实现进程间的数据传输和共享
消息队列
在鸿蒙操作系统中,消息队列由消息队列管理器来管理。进程可以通过向消息队列发送消息来实现数据传输,同时也可以通过接收消息来获取其他进程发送的数据。消息队列管理器负责将消息存储在队列中,并将其发送给目标进程共享内存
在鸿蒙操作系统中,共享内存由共享内存管理器来管理。进程可以通过映射共享内存到自己的地址空间中来获取共享内存的访问权限。通过读写共享内存中的数据,进程可以实现对数据的传输和共享远程过程调用
在鸿蒙操作系统中,远程过程调用由远程过程调用框架来实现。进程可以通过注册自己的函数或方法来提供服务,其他进程可以通过调用这些函数或方法来访问服务。远程过程调用框架负责将调用请求发送给目标进程,并将返回结果返回给调用方
着重讲一下鸿蒙内核进程间通信-共享内存
进程间通信的本质就是让不同的进程能够看到同一份资源,这样就提供了进程间通信的基础,而共享内存也是如此:
共享内存就是再物理内存中申请一片空间然后,如果有两个进程想要通信,那么就可以通过页表挂接到地址空间中,这样两个进程就能看到同一片资源。这样就可以通过对这片空间进行读写就可以了
管理部分
- 初始化共享内存,共享内存是以资源池的方式管理的,上来就为全局变量
g_shmSegs
向内核堆空间申请了g_shmInfo.shmmni
个struct shmIDSource
#define SHM_MNI 192 //共享内存总数 默认192
// 共享内存模块设置信息
struct shminfo {
unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];
};
STATIC struct shminfo g_shmInfo = { //描述共享内存范围的全局变量
.shmmax = SHM_MAX,//共享内存单个上限 4096页 即 16M
.shmmin = SHM_MIN,//共享内存单个下限 1页 即:4K
.shmmni = SHM_MNI,//共享内存总数 默认192
.shmseg = SHM_SEG,//每个用户进程可以使用的最多的共享内存段的数目 128
.shmall = SHM_ALL,//系统范围内共享内存的总页数,4096页
};
//共享内存初始化
UINT32 ShmInit(VOID)
{
// ..
ret = LOS_MuxInit(&g_sysvShmMux, NULL);//初始化互斥
g_shmSegs = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, sizeof(struct shmIDSource) * g_shmInfo.shmmni);//分配shm段数组
(VOID)memset_s(g_shmSegs, (sizeof(struct shmIDSource) * g_shmInfo.shmmni),
0, (sizeof(struct shmIDSource) * g_shmInfo.shmmni));//数组清零
for (i = 0; i < g_shmInfo.shmmni; i++) {
g_shmSegs[i].status = SHM_SEG_FREE;//节点初始状态为空闲
g_shmSegs[i].ds.shm_perm.seq = i + 1;//struct ipc_perm shm_perm;系统为每一个IPC对象保存一个ipc_perm结构体,结构说明了IPC对象的权限和所有者
LOS_ListInit(&g_shmSegs[i].node);//初始化节点
}
g_shmUsedPageCount = 0;
return LOS_OK;
}
- 系列篇多次提过,每个功能模块都至少有一个核心结构体来