资讯动态

仓颉语言 IPC Kit 进程间通信实战:ohos.rpc 模块 API 全解析与 RPC 错误码排障指南

发布时间:2026/10/17 23:22:50 来源:尧图企业网站定制
文档知识库教程OpenHarmony【免费下载链接】CangjieCorpus本仓库为仓颉编程语言语料库聚焦 仓颉编程语言 核心知识体系整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源经结构化处理与专业标注构建为支持 RAG检索增强生成技术 的高质量知识基座适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用推动鸿蒙开发生态智能化升级项目地址https://gitcode.com/Cangjie/CangjieCorpus点击查看免费下载本指南以 IPC Kit 官方 API 参考为骨架系统讲解仓颉语言在 OpenHarmony 上通过ohos.rpc模块实现设备内IPC与跨设备RPC进程间通信的核心能力Parcelable自定义序列化对象、Ashmem匿名共享内存以及承载一切数据传输的MessageSequence消息序列并逐一解读 1900001~1900013 系列 RPC 错误码的成因与处理步骤。读完本文你将能够基于仓颉模板工程直接编写可在index.cj中编译运行的 IPC/RPC 数据传递代码并在通信异常时依据错误码快速定位问题。一、IPC Kit 与 ohos.rpc模块定位与核心概念ohos.rpc是 IPC Kit进程间通信服务对外提供的仓颉 API 模块当前标注为Beta 特性。该模块提供两种进程间通信能力详见 IPC Kit 简介通信方式全称驱动适用场景IPCInter-Process Communication设备内进程间通信Binder 驱动后台服务通过 IPC 机制提供跨进程的服务调用能力RPCRemote Procedure Call设备间进程间通信软总线驱动多端协同中提供远端接口调用与数据传递能力之所以需要跨进程通信是因为每个进程都拥有独立的资源和内存空间其他进程不能随意访问IPC/RPC 正是为了突破这一限制而存在。通信通常采用客户端-服务端Client-Server模型客户端Client也称 Proxy获取服务端所在进程的代理对象通过代理读写数据实现进程间数据通信服务端Server也称 Stub处理请求后通过驱动返回结果。实际部署中Stub 会先向系统能力管理者System Ability ManagerSAMgr注册系统能力SAClient 需要先从 SAMgr 获取对应 SA 的 Proxy 对象才能与之通信。ohos.rpc模块正是为上述整套链路提供数据封装与传输底层的 API 集合。二、环境准备导入模块与示例工程说明2.1 导入模块所有 API 均通过kit.IPCKit包暴露导入方式如下import kit.IPCKit.*除 IPCKit 外示例代码中还常见两类辅助导入ohos.business_exception.BusinessException用于捕获通信与序列化异常kit.PerformanceAnalysisKit.Hilog用于打印日志import ohos.business_exception.BusinessException import kit.PerformanceAnalysisKit.Hilog2.2 示例代码使用约定官方 API 文档中的示例遵循两条约定详见 仓颉示例代码说明若示例代码首行有// index.cj注释表示该示例可在仓颉模板工程的index.cj文件中直接编译运行若示例需要获取 Context 应用上下文需在仓颉模板工程的main_ability.cj文件中进行配置。下文给出的代码片段均遵循上述约定可直接复制到对应文件中验证。三、interface Parcelable自定义对象的封送与解封Parcelable是仓颉侧自定义可序列化对象的统一接口用于在进程间通信期间将类的对象写入MessageSequence并从MessageSequence中恢复。public interface Parcelable { func marshalling(dataOut: MessageSequence): Bool func unmarshalling(dataIn: MessageSequence): Bool }系统能力SystemCapability.Communication.IPC.Core起始版本223.1 marshalling将对象封送进消息序列func marshalling(dataOut: MessageSequence): Bool参数名类型必填默认值说明dataOutMessageSequence是-可序列对象将被封送到的 MessageSequence 对象返回值类型为Booltrue表示封送成功false表示封送失败。3.2 unmarshalling从消息序列解封对象func unmarshalling(dataIn: MessageSequence): Bool参数名类型必填默认值说明dataInMessageSequence是-已将可序列对象封送到其中的 MessageSequence 对象返回值类型为Booltrue表示反序列化成功false表示反序列化失败。3.3 完整示例实现一个可序列化类并读写数组以下代码演示了自定义Parcelable类的完整实现配合writeParcelableArray/readParcelableArray实现数组级传输// index.cj import kit.IPCKit.* // 此处代码可添加在依赖项定义中 class MyParcelable : Parcelable { var num: Int32 0 var str: String init() {} init(num: Int32, str: String) { this.num num this.str str } public func marshalling(messageSequence: MessageSequence): Bool { messageSequence.writeInt(this.num) messageSequence.writeString(this.str) return true } public func unmarshalling(messageSequence: MessageSequence): Bool { this.num messageSequence.readInt() this.str messageSequence.readString() return true } } let parcelable MyParcelable(1, aaa) let parcelable2 MyParcelable(2, bbb) let parcelable3 MyParcelable(3, ccc) let data MessageSequence.create() data.writeParcelableArray(parcelable,parcelable2,parcelable3) let ret: ArrayParcelable [MyParcelable(0, ), MyParcelable(0, ), MyParcelable(0, )] data.readParcelableArray(ret)实现要点marshalling中按顺序调用写方法unmarshalling中必须按严格一致的顺序调用对应的读方法否则会触发错误码1900010读取与写入顺序不一致。四、class Ashmem匿名共享内存AshmemAnonymous Shared Memory用于在大数据量跨进程传输时避免整块数据复制。注意共享内存只适用于本设备内跨进程通信单个设备上跨进程通信的数据量超过 200KB 时官方建议使用匿名共享内存。public class Ashmem { public static const PROT_EXEC: UInt32 4 public static const PROT_NONE: UInt32 0 public static const PROT_READ: UInt32 1 public static const PROT_WRITE: UInt32 2 }系统能力SystemCapability.Communication.IPC.Core起始版本224.1 保护类型常量映射内存区域的保护类型由以下静态常量组合指定常量值含义PROT_EXEC4映射的内存可执行PROT_NONE0映射的内存不可访问PROT_READ1映射的内存可读PROT_WRITE2映射的内存可写典型用法是使用位或组合如Ashmem.PROT_READ | Ashmem.PROT_WRITE。4.2 创建 Ashmem 对象提供两个静态工厂方法① 按名称与大小创建public static func create(name: String, size: Int32): Ashmem参数名类型必填默认值说明nameString是-Ashmem 名称用于查询 Ashmem 信息长度不能为 0sizeInt32是-Ashmem 大小应大于 0以字节为单位② 复制已有 Ashmem 的文件描述符fd创建public static func create(ashmem: Ashmem): Ashmem参数名类型必填默认值说明ashmemAshmem是-已存在的 Ashmem 对象通过复制 fd 创建时两个 Ashmem 对象指向同一个共享内存区域可实现跨进程共享。4.3 映射、读写、保护与生命周期管理Ashmem 的完整使用流程是创建 → 映射 → 读写 → 取消映射 → 关闭核心方法如下方法签名功能相关错误码mapReadWriteAshmemfunc mapReadWriteAshmem(): Unit在本进程虚拟地址空间上创建可读写的共享文件映射1900001mapReadonlyAshmemfunc mapReadonlyAshmem(): Unit在本进程虚拟地址空间上创建只读的共享文件映射1900001mapTypedAshmemfunc mapTypedAshmem(mapType: UInt32): Unit按指定保护等级创建共享文件映射映射区域大小由此对象指定1900001getAshmemSizefunc getAshmemSize(): Int32获取 Ashmem 对象的内存大小-readDataFromAshmemfunc readDataFromAshmem(size: Int64, offset: Int64): Array\Byte从共享文件读取数据size 为读取大小offset 为读取起始位置1900004writeDataToAshmemfunc writeDataToAshmem(buf: Array\Byte, size: Int64, offset: Int64): Unit将数据写入共享文件buf 为写入数据1900003setProtectionTypefunc setProtectionType(protectionType: UInt32): Unit设置映射内存区域的保护等级1900002unmapAshmemfunc unmapAshmem(): Unit删除该 Ashmem 对象的地址映射-closeAshmemfunc closeAshmem(): Unit关闭这个 Ashmem-使用注意事项来自官方说明对 Ashmem 对象进行写操作前必须先调用mapReadWriteAshmem()完成映射关闭 Ashmem 对象前需要先解除地址映射先unmapAshmem()再closeAshmem()读取数据时需保证已映射区域具有PROT_READ权限写入时需具有PROT_WRITE权限。4.4 综合示例创建、映射、写入、读取与异常捕获// index.cj import kit.IPCKit.* import ohos.business_exception.BusinessException import kit.PerformanceAnalysisKit.Hilog try { let ashmem Ashmem.create(ashmem, 1024*1024) let ashmem2 Ashmem.create(ashmem) // 复制 fd两者指向同一共享内存区域 ashmem.mapReadWriteAshmem() // 写前必须映射为可读写 ashmem.writeDataToAshmem([1], 1, 0) let data ashmem.readDataFromAshmem(1, 0) ashmem.setProtectionType(Ashmem.PROT_READ) ashmem.unmapAshmem() ashmem.closeAshmem() // 关闭前需先解除映射 } catch (e: BusinessException) { Hilog.info(0, test, ${e.message}) }五、class MessageSequenceIPC/RPC 的数据载体MessageSequence是 IPC/RPC 通信中承载数据的核心对象。发送方使用其写方法将数据以特定格式写入接收方使用读方法按相同格式读出。支持的数据格式包括基础类型及数组、IPC 对象、接口描述符和自定义序列化对象。public class MessageSequence {}系统能力SystemCapability.Communication.IPC.Core起始版本225.1 创建与资源管理方法签名功能createstatic func create(): MessageSequence静态方法创建 MessageSequence 对象reclaimfunc reclaim(): Unit释放不再使用的 MessageSequence 对象closeFileDescriptorstatic func closeFileDescriptor(fd: Int32): Unit静态方法关闭给定的文件描述符dupFileDescriptorstatic func dupFileDescriptor(fd: Int32): Int32静态方法复制给定的文件描述符新 fd 作为返回值let data MessageSequence.create() // 创建消息序列 data.reclaim() // 用毕释放文件描述符操作示例配合 CoreFileKit 的FileIoimport kit.CoreFileKit.* let filePath path/to/file let file FileIo.open(filePath, mode: (OpenMode.CREATE | OpenMode.READ_WRITE)) let newFd MessageSequence.dupFileDescriptor(file.fd) // 复制 fd MessageSequence.closeFileDescriptor(file.fd) // 关闭 fddupFileDescriptor失败时抛出1900013Failed to call dup。5.2 容量与读写位置查询方法签名功能getSizefunc getSize(): UInt32获取当前数据大小字节setSizefunc setSize(size: UInt32): Unit设置对象中包含的数据大小字节getCapacityfunc getCapacity(): UInt32获取存储容量大小字节setCapacityfunc setCapacity(size: UInt32): Unit设置存储容量字节getRawDataCapacityfunc getRawDataCapacity(): UInt32获取可容纳的最大原始数据量即 128MBgetReadPositionfunc getReadPosition(): UInt32获取当前读取位置getWritePositionfunc getWritePosition(): UInt32获取当前写入位置rewindReadfunc rewindRead(pos: UInt32): Unit重新偏移读取位置到指定位置rewindWritefunc rewindWrite(pos: UInt32): Unit重新偏移写位置到指定位置getReadableBytesfunc getReadableBytes(): UInt32获取可读字节空间getWritableBytesfunc getWritableBytes(): UInt32获取可写字节空间containFileDescriptorsfunc containFileDescriptors(): Bool检查对象是否包含文件描述符setCapacity失败时可能抛出1900009或1900011内存分配失败rewindWrite失败时抛出1900009。5.3 基础类型读写MessageSequence提供与仓颉基础类型一一对应的读写方法读写必须严格按序配对。所有写方法失败时抛出1900009向 MessageSequence 写入数据失败所有读方法失败时抛出1900010读取 MessageSequence 数据失败。类型写方法读方法返回类型布尔值writeBoolean(val: Bool)readBoolean()Bool字节writeByte(val: Int8)readByte()Int8字符writeChar(val: UInt8)readChar()UInt8短整型writeShort(val: Int16)readShort()Int16整型writeInt(val: Int32)readInt()Int32长整型writeLong(val: Int64)readLong()Int64单精度浮点writeFloat(val: Float32)readFloat()Float32双精度浮点writeDouble(val: Float64)readDouble()Float64字符串writeString(val: String)readString()String基础类型写入示例let data MessageSequence.create() data.writeBoolean(false) data.writeByte(2) data.writeChar(97) data.writeShort(8) data.writeInt(10) data.writeLong(10000) data.writeFloat(1.2) data.writeDouble(10.2) data.writeString(abc)长度限制重要writeString的字符串值长度应小于 40960 字节writeInterfaceToken的接口描述符长度同样应小于 40960 字节详见下文 5.6 节。5.4 数组读写所有数组读写方法与基础类型成对提供写失败抛1900009、读失败抛1900010数组类型写方法读方法Array\BoolwriteBooleanArray(booleanArray)readBooleanArray()Array\Int8writeByteArray(byteArray)readByteArray()Array\UInt8writeUInt8Array(buf)readUInt8Array()Array\UInt16writeUInt16Array(buf)readUInt16Array()Array\UInt32writeUInt32Array(buf)readUInt32Array()Array\UInt64writeUInt64Array(buf)readUInt64Array()Array\Int16writeShortArray(shortArray)readShortArray()Array\Int32writeIntArray(intArray)readIntArray()Array\Int64writeLongArray(longArray)readLongArray()Array\Float32writeFloatArray(floatArray)readFloatArray()Array\Float64writeDoubleArray(doubleArray)readDoubleArray()Array\UInt8字符数组writeCharArray(charArray)readCharArray()Array\StringwriteStringArray(stringArray)readStringArray()数组读写示例let data MessageSequence.create() data.writeBooleanArray([false, true, false]) data.writeIntArray([1]) data.writeLongArray([1]) data.writeFloatArray([1.1]) data.writeDoubleArray([1.1]) data.writeStringArray([abc, def]) data.writeUInt16Array([1]) data.writeUInt32Array([1]) data.writeUInt64Array([1]) data.writeUInt8Array([1]) data.writeByteArray([1]) data.writeCharArray([97, 98, 88])writeStringArray要求数组单个元素的长度小于 40960 字节。5.5 自定义序列化对象Parcelable读写针对实现Parcelable接口的自定义对象提供泛型读写方法泛型约束T : Parcelable失败时抛出1900009/1900010可能附带1900012JS 回调失败方法签名功能writeParcelablefunc writeParcelable\T(val: T): Unit where T : Parcelable将自定义序列化对象写入 MessageSequencereadParcelablefunc readParcelable\T(dataIn: T): Unit where T : Parcelable从 MessageSequence 读取成员变量到指定对象 dataInwriteParcelableArrayfunc writeParcelableArray\T(parcelableArray: Array\T): Unit where T : Parcelable将可序列化对象数组写入 MessageSequencereadParcelableArrayfunc readParcelableArray\T(parcelableArray: Array\T): Unit where T : Parcelable从 MessageSequence 读取可序列化对象数组单个对象的写入与读出示例注意读出时需先构造一个目标对象实例let parcelable MyParcelable(1, aaa) let data MessageSequence.create() data.writeParcelable(parcelable) let ret MyParcelable() data.readParcelable(ret)5.6 文件描述符、Ashmem、原始数据、接口描述符与异常方法签名功能错误码writeFileDescriptorfunc writeFileDescriptor(fd: Int32): Unit写入文件描述符到 MessageSequence1900009readFileDescriptorfunc readFileDescriptor(): Int32从 MessageSequence 读取文件描述符1900010writeAshmemfunc writeAshmem(ashmem: Ashmem): Unit将匿名共享对象写入 MessageSequence1900003readAshmemfunc readAshmem(): Ashmem从 MessageSequence 读取匿名共享对象1900004writeRawDataBufferfunc writeRawDataBuffer(rawData: Array\Byte, size: Int64): Unit将原始数据写入 MessageSequence1900009readRawDataBufferfunc readRawDataBuffer(size: Int64): Array\Byte从 MessageSequence 读取原始数据1900010writeInterfaceTokenfunc writeInterfaceToken(token: String): Unit将接口描述符写入 MessageSequence远端对象可用其校验本次通信1900009readInterfaceTokenfunc readInterfaceToken(): String读取接口描述符按写入顺序读取本地对象可用其校验通信1900010writeNoExceptionfunc writeNoException(): Unit写入指示未发生异常的信息1900009readExceptionfunc readException(): Unit从 MessageSequence 中读取异常1900010原始数据RawData接口的两条关键限制writeRawDataBuffer是一次性接口不允许在一次 parcel 通信中多次调用当数据量较大超过 32KB时该接口会改用共享内存传输数据此时需注意selinux 配置原始数据大小不能超过 128MB与getRawDataCapacity()返回值一致。接口描述符校验是 IPC 安全机制的重要一环发送方writeInterfaceToken(...)写入标识接收方readInterfaceToken()读取后进行比对以确认通信双方接口一致。六、RPC 错误码速查与排障指引ohos.rpc模块的异常统一通过BusinessException抛出错误码完整定义见 RPC 错误码。常用捕获模板如下try { // IPC/RPC 操作 } catch (e: BusinessException) { Hilog.info(0, test, ${e.message}) }6.1 错误码总览错误码错误信息触发场景1900001Failed to call mmap.执行系统调用 mmap 失败Ashmem 映射1900002Failed to call ioctl.在共享内存文件描述符上执行系统调用 ioctl 失败1900003Failed to write data to the shared memory.向共享内存写数据失败1900004Failed to read data from the shared memory.从共享内存读数据失败1900005Operation allowed only for the proxy object.在 RemoteObject 上调用了只有 RemoteProxy 支持的方法1900006Operation allowed only for the remote object.在 RemoteProxy 上调用了只有 RemoteObject 支持的方法1900007Communication failed.和远端对象进行进程间通信失败1900008The proxy or remote object is invalid.非法的代理对象或者远端对象1900009Failed to write data to the message sequence.向 MessageSequence 写数据失败sequence 默认空间已满1900010Failed to read data from the message sequence.读取 MessageSequence 数据失败读写顺序不一致1900011Memory allocation failed.序列化过程中内存分配失败写入数据过大1900012Failed to call the JS callback function.执行 JS 回调方法失败1900013Failed to call dup.执行系统调用 dup 失败6.2 高频错误码排查步骤1900001mmap 失败① 检查Ashmem.create()是否指定了超大内存② 检查执行映射时系统是否有足够内存可用可能原因映射区域过大、系统内存压力大。1900002ioctl 失败① 检查调用setProtectionType指定的参数是否来自Ashmem类的PROT_EXEC、PROT_READ、PROT_WRITE常量② 检查指定参数是否为映射共享内存时所指类型的子集可能原因参数为内核非法参数、类型超出映射时指定的类型。1900003 / 1900004共享内存读写失败① 检查单次写或连续写的总内容是否超过了映射的共享内存大小② 检查是否设置了PROT_WRITE/PROT_READ保护权限。1900007远端通信失败① 检查远端对象是否已销毁② 检查是否注册了死亡监听且远端对象发生析构后又重新创建本端持有的代理对象已过期。1900009写入 MessageSequence 失败sequence 默认空间已满请使用 MessageSequence 提供的获取缓冲区空间相关方法如getWritableBytes、getCapacity确认是否还有剩余空间。1900010读取 MessageSequence 失败读取和写入顺序不一致请保证读取顺序与写入顺序严格一致。1900011内存分配失败写入的数据过大请检查写入的数据或设置的参数是否过大。1900013dup 失败① 检查入参 fd 是否依然有效② 排查进程是否已耗尽文件句柄资源。七、约束与限制实战前必读根据 IPC Kit 简介使用ohos.rpc前还需注意以下约束单个设备上跨进程通信时传输的数据量最大为 200KB过大的数据量请使用匿名共享内存Ashmem不支持在 RPC 中订阅匿名 Stub 对象未向 SAMgr 注册的 Stub 对象的死亡通知不支持把跨设备的 Proxy 对象传递回该 Proxy 对象所指向的 Stub 对象所在的设备即指向远端设备 Stub 的 Proxy 对象不能在本设备内进行二次跨进程传递Stage 模型不能直接使用本文介绍的 IPC 和 RPC需结合具体场景后台服务跨进程调用、多端协同远端调用进行设计。八、结语与进一步阅读ohos.rpc模块以MessageSequence为统一数据载体通过Parcelable支持任意自定义对象的序列化通过Ashmem支持大块共享内存传输配合 1900001~1900013 系列错误码实现可诊断的异常处理构成了仓颉语言在 OpenHarmony 上进行 IPC/RPC 通信的完整 API 底座。开发者可将本文示例直接放入仓颉模板工程index.cj/main_ability.cj编译运行进一步验证读写配对、权限保护与容量管理等关键行为。相关文档与源码索引IPC Kit API 参考模块入口ohos.rpcRPC 通信API 全量参考RPC 错误码IPC Kit 简介实现原理与约束仓颉示例代码说明Context 应用上下文 API赞分享文档知识库教程OpenHarmony【免费下载链接】CangjieCorpus本仓库为仓颉编程语言语料库聚焦 仓颉编程语言 核心知识体系整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源经结构化处理与专业标注构建为支持 RAG检索增强生成技术 的高质量知识基座适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用推动鸿蒙开发生态智能化升级项目地址https://gitcode.com/Cangjie/CangjieCorpus点击查看免费下载相关推荐仓颉文件管理错误码全解析OpenHarmony Core File Kit 五大类错误码排查指南仓颉文件管理错误码全解析OpenHarmony Core File Kit 五大类错误码排查指南 本文基于 CangjieCorpus 仓库中 文件管理错误码文档知识库教程OpenHarmony仓颉 Crypto Architecture Kit 错误码全解析17620001 / 17620002 / 17630001 的成因与排查指南仓颉 Crypto Architecture Kit 错误码全解析17620001 / 17620002 / 17630001 的成因与排查指南 导读 Cry文档知识库教程OpenHarmony仓颉 Camera Kit 相机错误码完全指南7400101—7400201 含义、成因与排查实战仓颉 Camera Kit 相机错误码完全指南7400101—7400201 含义、成因与排查实战 本文聚焦鸿蒙OpenHarmony仓颉 Camera文档知识库教程OpenHarmony上一篇如何在3分钟内将单机游戏变身多人派对Nucleus Co-Op的神奇魔法下一篇零基础AI换脸神器roop-unleashed5分钟实现专业级面部替换无需训练直接上手创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑