1e41f4b71Sopenharmony_ci# Native子进程开发指导(C/C++) 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci本模块提供了两种创建子进程的方式,开发者可根据需要进行选择。 4e41f4b71Sopenharmony_ci- [创建支持IPC回调的子进程](#创建支持ipc回调的子进程):创建子进程,并在父子进程间建立IPC通道,适用于父子进程需要IPC通信的场景。对[IPCKit](../ipc/ipc-capi-development-guideline.md)存在依赖。 5e41f4b71Sopenharmony_ci- [创建支持参数传递的子进程](#创建支持参数传递的子进程):创建子进程,并传递字符串和fd句柄参数到子进程。适用于需要传递参数到子进程的场景。 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci 8e41f4b71Sopenharmony_ci## 创建支持IPC回调的子进程 9e41f4b71Sopenharmony_ci 10e41f4b71Sopenharmony_ci### 场景介绍 11e41f4b71Sopenharmony_ci 12e41f4b71Sopenharmony_ci本章节介绍如何在主进程中创建Native子进程,并在父子进程间建立IPC通道,方便开发者在Native层进行多进程编程。 13e41f4b71Sopenharmony_ci 14e41f4b71Sopenharmony_ci### 接口说明 15e41f4b71Sopenharmony_ci 16e41f4b71Sopenharmony_ci| 名称 | 描述 | 17e41f4b71Sopenharmony_ci| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | 18e41f4b71Sopenharmony_ci| int [OH_Ability_CreateNativeChildProcess](../reference/apis-ability-kit/c-apis-ability-childprocess.md#oh_ability_createnativechildprocess) (const char *libName, [OH_Ability_OnNativeChildProcessStarted](../reference/apis-ability-kit/c-apis-ability-childprocess.md#oh_ability_onnativechildprocessstarted) onProcessStarted) | 创建子进程并加载参数中指定的动态链接库文件,进程启动结果通过回调参数异步通知,需注意回调通知为独立线程,回调函数实现需要注意线程同步,且不能执行高耗时操作避免长时间阻塞。 | 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ci> **说明:** 21e41f4b71Sopenharmony_ci> 22e41f4b71Sopenharmony_ci> 当前仅支持2in1设备,且单个进程只能启动一个Native子进程。 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci### 开发步骤 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ci基于已创建完成的Native应用开发工程,在此基础上介绍如何使用`AbilityKit`提供的C API接口,创建Native子进程,并同时在父子进程间建立IPC通道。 27e41f4b71Sopenharmony_ci 28e41f4b71Sopenharmony_ci**动态库文件** 29e41f4b71Sopenharmony_ci 30e41f4b71Sopenharmony_ci```txt 31e41f4b71Sopenharmony_cilibipc_capi.so 32e41f4b71Sopenharmony_cilibchild_process.so 33e41f4b71Sopenharmony_ci``` 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci**头文件** 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci```c++ 38e41f4b71Sopenharmony_ci#include <IPCKit/ipc_kit.h> 39e41f4b71Sopenharmony_ci#include <AbilityKit/native_child_process.h> 40e41f4b71Sopenharmony_ci``` 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ci1. 子进程-实现必要的导出方法。 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ci 在子进程中,实现必要的两个函数**NativeChildProcess_OnConnect**及**NativeChildProcess_MainProc**并导出(假设代码所在的文件名为ChildProcessSample.cpp)。其中NativeChildProcess_OnConnect方法返回的OHIPCRemoteStub对象负责主进程进行IPC通信,具体实现方法请参考[IPC通信开发指导(C/C++)](../ipc/ipc-capi-development-guideline.md),本文不再赘述。 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ci 子进程启动后会先调用NativeChildProcess_OnConnect获取IPC Stub对象,之后再调用NativeChildProcess_MainProc移交主线程控制权,该函数返回后子进程随即退出。 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci ```c++ 49e41f4b71Sopenharmony_ci #include <IPCKit/ipc_kit.h> 50e41f4b71Sopenharmony_ci 51e41f4b71Sopenharmony_ci extern "C" { 52e41f4b71Sopenharmony_ci 53e41f4b71Sopenharmony_ci OHIPCRemoteStub* NativeChildProcess_OnConnect() 54e41f4b71Sopenharmony_ci { 55e41f4b71Sopenharmony_ci // ipcRemoteStub指向子进程实现的ipc stub对象,用于接收来自主进程的IPC消息并响应 56e41f4b71Sopenharmony_ci // 子进程根据业务逻辑控制其生命周期 57e41f4b71Sopenharmony_ci return ipcRemoteStub; 58e41f4b71Sopenharmony_ci } 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_ci void NativeChildProcess_MainProc() 61e41f4b71Sopenharmony_ci { 62e41f4b71Sopenharmony_ci // 相当于子进程的Main函数,实现子进程的业务逻辑 63e41f4b71Sopenharmony_ci // ... 64e41f4b71Sopenharmony_ci // 函数返回后子进程随即退出 65e41f4b71Sopenharmony_ci } 66e41f4b71Sopenharmony_ci 67e41f4b71Sopenharmony_ci } // extern "C" 68e41f4b71Sopenharmony_ci ``` 69e41f4b71Sopenharmony_ci 70e41f4b71Sopenharmony_ci2. 子进程-编译为动态链接库。 71e41f4b71Sopenharmony_ci 72e41f4b71Sopenharmony_ci 修改CMakeList.txt文件,编译为动态链接库(假设需要编译出的库文件名称为libchildprocesssample.so),并添加IPC动态库依赖。 73e41f4b71Sopenharmony_ci 74e41f4b71Sopenharmony_ci ```txt 75e41f4b71Sopenharmony_ci add_library(childprocesssample SHARED 76e41f4b71Sopenharmony_ci # 实现必要导出方法的源文件 77e41f4b71Sopenharmony_ci ChildProcessSample.cpp 78e41f4b71Sopenharmony_ci 79e41f4b71Sopenharmony_ci # 其它代码源文件 80e41f4b71Sopenharmony_ci # ... 81e41f4b71Sopenharmony_ci ) 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ci target_link_libraries(childprocesssample PUBLIC 84e41f4b71Sopenharmony_ci # 添加依赖的IPC动态库 85e41f4b71Sopenharmony_ci libipc_capi.so 86e41f4b71Sopenharmony_ci 87e41f4b71Sopenharmony_ci # 其它所依赖的动态库 88e41f4b71Sopenharmony_ci # ... 89e41f4b71Sopenharmony_ci ) 90e41f4b71Sopenharmony_ci ``` 91e41f4b71Sopenharmony_ci 92e41f4b71Sopenharmony_ci3. 主进程-实现子进程启动结果回调函数。 93e41f4b71Sopenharmony_ci 94e41f4b71Sopenharmony_ci ```c++ 95e41f4b71Sopenharmony_ci #include <IPCKit/ipc_kit.h> 96e41f4b71Sopenharmony_ci 97e41f4b71Sopenharmony_ci static void OnNativeChildProcessStarted(int errCode, OHIPCRemoteProxy *remoteProxy) 98e41f4b71Sopenharmony_ci { 99e41f4b71Sopenharmony_ci if (errCode != NCP_NO_ERROR) { 100e41f4b71Sopenharmony_ci // 子进程未能正常启动时的异常处理 101e41f4b71Sopenharmony_ci // ... 102e41f4b71Sopenharmony_ci return; 103e41f4b71Sopenharmony_ci } 104e41f4b71Sopenharmony_ci 105e41f4b71Sopenharmony_ci // 保存remoteProxy对象,后续基于IPC Kit提供的API同子进程间进行IPC通信 106e41f4b71Sopenharmony_ci // 耗时操作建议转移到独立线程去处理,避免长时间阻塞回调线程 107e41f4b71Sopenharmony_ci // IPC对象使用完毕后,需要调用OH_IPCRemoteProxy_Destroy方法释放 108e41f4b71Sopenharmony_ci // ... 109e41f4b71Sopenharmony_ci } 110e41f4b71Sopenharmony_ci ``` 111e41f4b71Sopenharmony_ci 112e41f4b71Sopenharmony_ci 回调函数传递的第二个参数OHIPCRemoteProxy对象,会与子进程实现的**NativeChildProcess_OnConnect**方法返回的OHIPCRemoteStub对象间建立IPC通道,具体使用方法参考[IPC通信开发指导(C/C++)](../ipc/ipc-capi-development-guideline.md),本文不再赘述;OHIPCRemoteProxy对象使用完毕后,需要调用[OH_IPCRemoteProxy_Destory](../reference/apis-ipc-kit/_o_h_i_p_c_remote_object.md#oh_ipcremoteproxy_destroy)函数释放。 113e41f4b71Sopenharmony_ci 114e41f4b71Sopenharmony_ci4. 主进程-启动Native子进程。 115e41f4b71Sopenharmony_ci 116e41f4b71Sopenharmony_ci 调用API启动Native子进程,需要注意返回值为NCP_NO_ERROR仅代表成功调用native子进程启动逻辑,实际的启动结果通过第二个参数中指定的回调函数异步通知。需注意**仅允许在主进程中创建子进程**。 117e41f4b71Sopenharmony_ci 118e41f4b71Sopenharmony_ci ```c++ 119e41f4b71Sopenharmony_ci #include <AbilityKit/native_child_process.h> 120e41f4b71Sopenharmony_ci 121e41f4b71Sopenharmony_ci // 第一个参数"libchildprocesssample.so"为实现了子进程必要导出方法的动态库文件名称 122e41f4b71Sopenharmony_ci int32_t ret = OH_Ability_CreateNativeChildProcess("libchildprocesssample.so", OnNativeChildProcessStarted); 123e41f4b71Sopenharmony_ci if (ret != NCP_NO_ERROR) { 124e41f4b71Sopenharmony_ci // 子进程未能正常启动时的异常处理 125e41f4b71Sopenharmony_ci // ... 126e41f4b71Sopenharmony_ci } 127e41f4b71Sopenharmony_ci ``` 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci5. 主进程-添加编译依赖项。 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ci 修改CMaklist.txt添加必要的依赖库,假设主进程所在的so名称为libmainprocesssample.so(主进程和子进程的实现也可以选择编译到同一个动态库文件)。 132e41f4b71Sopenharmony_ci 133e41f4b71Sopenharmony_ci ```txt 134e41f4b71Sopenharmony_ci target_link_libraries(mainprocesssample PUBLIC 135e41f4b71Sopenharmony_ci # 添加依赖的IPC及元能力动态库 136e41f4b71Sopenharmony_ci libipc_capi.so 137e41f4b71Sopenharmony_ci libchild_process.so 138e41f4b71Sopenharmony_ci 139e41f4b71Sopenharmony_ci # 其它依赖的动态库 140e41f4b71Sopenharmony_ci # ... 141e41f4b71Sopenharmony_ci ) 142e41f4b71Sopenharmony_ci ``` 143e41f4b71Sopenharmony_ci 144e41f4b71Sopenharmony_ci## 创建支持参数传递的子进程 145e41f4b71Sopenharmony_ci 146e41f4b71Sopenharmony_ci### 场景介绍 147e41f4b71Sopenharmony_ci 148e41f4b71Sopenharmony_ci本章节介绍如何创建Native子进程,并传递参数到子进程。 149e41f4b71Sopenharmony_ci 150e41f4b71Sopenharmony_ci### 接口说明 151e41f4b71Sopenharmony_ci 152e41f4b71Sopenharmony_ci| 名称 | 描述 | 153e41f4b71Sopenharmony_ci| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | 154e41f4b71Sopenharmony_ci| [Ability_NativeChildProcess_ErrCode](../reference/apis-ability-kit/c-apis-ability-childprocess.md#ability_nativechildprocess_errcode) [OH_Ability_StartNativeChildProcess](../reference/apis-ability-kit/c-apis-ability-childprocess.md#oh_ability_startnativechildprocess) (const char \*entry, [NativeChildProcess_Args](../reference/apis-ability-kit/c-apis-ability-childprocess.md#nativechildprocess_args) args, [NativeChildProcess_Options](../reference/apis-ability-kit/c-apis-ability-childprocess.md#nativechildprocess_options) options, int32_t *pid) | 启动子进程并返回子进程pid。 | 155e41f4b71Sopenharmony_ci 156e41f4b71Sopenharmony_ci### 开发步骤 157e41f4b71Sopenharmony_ci 158e41f4b71Sopenharmony_ci 159e41f4b71Sopenharmony_ci**动态库文件** 160e41f4b71Sopenharmony_ci 161e41f4b71Sopenharmony_ci```txt 162e41f4b71Sopenharmony_cilibchild_process.so 163e41f4b71Sopenharmony_ci``` 164e41f4b71Sopenharmony_ci 165e41f4b71Sopenharmony_ci**头文件** 166e41f4b71Sopenharmony_ci 167e41f4b71Sopenharmony_ci```c++ 168e41f4b71Sopenharmony_ci#include <AbilityKit/native_child_process.h> 169e41f4b71Sopenharmony_ci``` 170e41f4b71Sopenharmony_ci 171e41f4b71Sopenharmony_ci1. 子进程-实现必要的导出方法。 172e41f4b71Sopenharmony_ci 173e41f4b71Sopenharmony_ci 在子进程中,实现参数为[NativeChildProcess_Args](../reference/apis-ability-kit/c-apis-ability-childprocess.md#nativechildprocess_args)入口函数并导出(假设代码所在的文件名为ChildProcessSample.cpp)。子进程启动后会调用该入口函数,该函数返回后子进程随即退出。 174e41f4b71Sopenharmony_ci 175e41f4b71Sopenharmony_ci ```c++ 176e41f4b71Sopenharmony_ci #include <AbilityKit/native_child_process.h> 177e41f4b71Sopenharmony_ci 178e41f4b71Sopenharmony_ci extern "C" { 179e41f4b71Sopenharmony_ci 180e41f4b71Sopenharmony_ci /** 181e41f4b71Sopenharmony_ci * 子进程的入口函数,实现子进程的业务逻辑 182e41f4b71Sopenharmony_ci * 函数名称可以自定义,在主进程调用OH_Ability_StartNativeChildProcess方法时指定,此示例中为Main 183e41f4b71Sopenharmony_ci * 函数返回后子进程退出 184e41f4b71Sopenharmony_ci */ 185e41f4b71Sopenharmony_ci void Main(NativeChildProcess_Args args) 186e41f4b71Sopenharmony_ci { 187e41f4b71Sopenharmony_ci // 获取传入的entryPrams 188e41f4b71Sopenharmony_ci char *entryParams = args.entryParams; 189e41f4b71Sopenharmony_ci // 获取传入的fd列表 190e41f4b71Sopenharmony_ci NativeChildProcess_Fd *current = args.fdList.head; 191e41f4b71Sopenharmony_ci while (current != nullptr) { 192e41f4b71Sopenharmony_ci char *fdName = current->fdName; 193e41f4b71Sopenharmony_ci int32_t fd = current->fd; 194e41f4b71Sopenharmony_ci current = current->next; 195e41f4b71Sopenharmony_ci // 业务逻辑.. 196e41f4b71Sopenharmony_ci } 197e41f4b71Sopenharmony_ci } 198e41f4b71Sopenharmony_ci } // extern "C" 199e41f4b71Sopenharmony_ci ``` 200e41f4b71Sopenharmony_ci 201e41f4b71Sopenharmony_ci2. 子进程-编译为动态链接库。 202e41f4b71Sopenharmony_ci 203e41f4b71Sopenharmony_ci 修改CMakeList.txt文件,编译为动态链接库(假设需要编译出的库文件名称为libchildprocesssample.so),并添加元能力动态库依赖。 204e41f4b71Sopenharmony_ci 205e41f4b71Sopenharmony_ci ```txt 206e41f4b71Sopenharmony_ci add_library(childprocesssample SHARED 207e41f4b71Sopenharmony_ci # 实现必要导出方法的源文件 208e41f4b71Sopenharmony_ci ChildProcessSample.cpp 209e41f4b71Sopenharmony_ci 210e41f4b71Sopenharmony_ci # 其它代码源文件 211e41f4b71Sopenharmony_ci # ... 212e41f4b71Sopenharmony_ci ) 213e41f4b71Sopenharmony_ci 214e41f4b71Sopenharmony_ci target_link_libraries(childprocesssample PUBLIC 215e41f4b71Sopenharmony_ci # 添加依赖的元能力动态库 216e41f4b71Sopenharmony_ci libchild_process.so 217e41f4b71Sopenharmony_ci 218e41f4b71Sopenharmony_ci # 其它所依赖的动态库 219e41f4b71Sopenharmony_ci # ... 220e41f4b71Sopenharmony_ci ) 221e41f4b71Sopenharmony_ci ``` 222e41f4b71Sopenharmony_ci 223e41f4b71Sopenharmony_ci3. 主进程-启动Native子进程。 224e41f4b71Sopenharmony_ci 225e41f4b71Sopenharmony_ci 调用API启动Native子进程,返回值为NCP_NO_ERROR代表成功启动native子进程。 226e41f4b71Sopenharmony_ci 227e41f4b71Sopenharmony_ci ```c++ 228e41f4b71Sopenharmony_ci #include <AbilityKit/native_child_process.h> 229e41f4b71Sopenharmony_ci #include <stdlib.h> 230e41f4b71Sopenharmony_ci #include <string.h> 231e41f4b71Sopenharmony_ci #include <fcntl.h> 232e41f4b71Sopenharmony_ci 233e41f4b71Sopenharmony_ci void startNativeChildProcess() 234e41f4b71Sopenharmony_ci { 235e41f4b71Sopenharmony_ci // ... 236e41f4b71Sopenharmony_ci NativeChildProcess_Args args; 237e41f4b71Sopenharmony_ci // 设置entryParams,支持传输的最大数据量为150KB 238e41f4b71Sopenharmony_ci args.entryParams = (char*)malloc(sizeof(char) * 10); 239e41f4b71Sopenharmony_ci (void)strcpy(args.entryParams, "testParam"); 240e41f4b71Sopenharmony_ci 241e41f4b71Sopenharmony_ci // 插入节点到链表头节点中 242e41f4b71Sopenharmony_ci args.fdList.head = (NativeChildProcess_Fd*)malloc(sizeof(NativeChildProcess_Fd)); 243e41f4b71Sopenharmony_ci // fd关键字,最多不超过20个字符 244e41f4b71Sopenharmony_ci args.fdList.head->fdName = (char*)malloc(sizeof(char) * 4); 245e41f4b71Sopenharmony_ci (void)strcpy(args.fdList.head->fdName, "fd1"); 246e41f4b71Sopenharmony_ci // 获取fd逻辑 247e41f4b71Sopenharmony_ci int32_t fd = open("/data/storage/el2/base/haps/entry/files/test.txt", O_RDWR | O_CREAT, 0644); 248e41f4b71Sopenharmony_ci args.fdList.head->fd = fd; 249e41f4b71Sopenharmony_ci // 此处只插入一个fd记录,根据需求可以插入更多fd记录到链表中,最多不超过16个 250e41f4b71Sopenharmony_ci args.fdList.head->next = NULL; 251e41f4b71Sopenharmony_ci NativeChildProcess_Options options = { 252e41f4b71Sopenharmony_ci .isolationMode = NCP_ISOLATION_MODE_ISOLATED 253e41f4b71Sopenharmony_ci }; 254e41f4b71Sopenharmony_ci 255e41f4b71Sopenharmony_ci // 第一个参数"libchildprocesssample.so:Main"为实现了子进程Main方法的动态库文件名称和入口方法名 256e41f4b71Sopenharmony_ci int32_t pid = -1; 257e41f4b71Sopenharmony_ci Ability_NativeChildProcess_ErrCode ret = OH_Ability_StartNativeChildProcess( 258e41f4b71Sopenharmony_ci "libchildprocesssample.so:Main", args, options, &pid); 259e41f4b71Sopenharmony_ci if (ret != NCP_NO_ERROR) { 260e41f4b71Sopenharmony_ci // 释放NativeChildProcess_Args中的内存空间防止内存泄漏 261e41f4b71Sopenharmony_ci // 子进程未能正常启动时的异常处理 262e41f4b71Sopenharmony_ci // ... 263e41f4b71Sopenharmony_ci } 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ci // 其他逻辑 266e41f4b71Sopenharmony_ci // ... 267e41f4b71Sopenharmony_ci 268e41f4b71Sopenharmony_ci // 释放NativeChildProcess_Args中的内存空间防止内存泄漏 269e41f4b71Sopenharmony_ci } 270e41f4b71Sopenharmony_ci ``` 271e41f4b71Sopenharmony_ci 272e41f4b71Sopenharmony_ci4. 主进程-添加编译依赖项。 273e41f4b71Sopenharmony_ci 274e41f4b71Sopenharmony_ci 修改CMaklist.txt添加必要的依赖库,假设主进程所在的so名称为libmainprocesssample.so(主进程和子进程的实现也可以选择编译到同一个动态库文件)。 275e41f4b71Sopenharmony_ci 276e41f4b71Sopenharmony_ci ```txt 277e41f4b71Sopenharmony_ci target_link_libraries(mainprocesssample PUBLIC 278e41f4b71Sopenharmony_ci # 添加依赖的元能力动态库 279e41f4b71Sopenharmony_ci libchild_process.so 280e41f4b71Sopenharmony_ci 281e41f4b71Sopenharmony_ci # 其它依赖的动态库 282e41f4b71Sopenharmony_ci # ... 283e41f4b71Sopenharmony_ci ) 284e41f4b71Sopenharmony_ci ``` 285