1# Native Child Process Development (C/C++) 2 3You can create a child process in either of the following ways: 4- [Creating a Child Process That Supports IPC Callback](#creating-a-child-process-that-supports-ipc-callback): Create a child process and establish an IPC channel between the parent and child processes. This method applies to scenarios where the parent and child processes require IPC. Its usage depends on [IPC Kit](../ipc/ipc-capi-development-guideline.md). 5- [Creating a Child Process That Supports Pass-by-Parameter](#creating-a-child-process-that-supports-pass-by-parameter): Create a child process and pass the string and FD handle parameters to the child process. This method applies to scenarios where parameters need to be passed to child processes. 6 7 8## Creating a Child Process That Supports IPC Callback 9 10### When to Use 11 12This topic describes how to create a native child process in the main process and establish an IPC channel between the main process and child process. It makes multi-process programming at the native layer easier. 13 14### Available APIs 15 16| Name | Description | 17| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | 18| 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) | Creates a child process, loads a specified dynamic link library, and returns the startup result asynchronously through a callback parameter. An independent thread is used to execute the callback function. When implementing the callback function, pay attention to thread synchronization issues and avoid performing time-consuming operations to prevent extended blocking.| 19 20> **NOTE** 21> 22> This function is valid only for 2-in-1 devices. 23> 24> Since API version 15, a single process supports a maximum of 50 native child processes. In API version 14 and earlier versions, a single process supports only one native child process. 25 26### How to Develop 27 28This section describes how to use the C APIs provided by Ability Kit to create a native child process and establish an IPC channel between the main process and child process based on an existing native application development project. 29 30**Linking Dynamic Libraries** 31 32```txt 33libipc_capi.so 34libchild_process.so 35``` 36 37**Including Header Files** 38 39```c++ 40#include <IPCKit/ipc_kit.h> 41#include <AbilityKit/native_child_process.h> 42``` 43 441. (Child process) Implement necessary export functions. 45 46 In the child process, implement and export the functions **NativeChildProcess_OnConnect** and **NativeChildProcess_MainProc**. (It is assumed that the code file is named **ChildProcessSample.cpp**.) The **OHIPCRemoteStub** object returned by **NativeChildProcess_OnConnect** is responsible for IPC of the main process. For details, see [IPC Development (C/C++)](../ipc/ipc-capi-development-guideline.md). 47 48 After the child process is started, **NativeChildProcess_OnConnect** is invoked to obtain an IPC stub object, and then **NativeChildProcess_MainProc** is called to transfer the control right of the main thread. After the second function is returned, the child process exits. 49 50 ```c++ 51 #include <IPCKit/ipc_kit.h> 52 53 extern "C" { 54 55 OHIPCRemoteStub* NativeChildProcess_OnConnect() 56 { 57 // ipcRemoteStub points to the IPC stub object implemented by the child process. The object is used to receive and respond to IPC messages from the main process. 58 // The child process controls its lifecycle according to the service logic. 59 return ipcRemoteStub; 60 } 61 62 void NativeChildProcess_MainProc() 63 { 64 // Equivalent to the Main function of the child process. It implements the service logic of the child process. 65 // ... 66 // After the function is returned, the child process exits. 67 } 68 69 } // extern "C" 70 ``` 71 722. (Child process) Compile a dynamic link library. 73 74 Modify the **CMakeList.txt** file, compile the file into a dynamic link library (named **libchildprocesssample.so** in this example), and add the dependency of the dynamic link library of IPC Kit. 75 76 ```txt 77 add_library(childprocesssample SHARED 78 # Source code file that implements the necessary export functions 79 ChildProcessSample.cpp 80 81 # Other source code files 82 # ... 83 ) 84 85 target_link_libraries(childprocesssample PUBLIC 86 # Add the dependency of the dynamic link library of IPC Kit. 87 libipc_capi.so 88 89 # Dependencies of other dynamic link libraries 90 # ... 91 ) 92 ``` 93 943. (Main process) Implement the child process startup result callback. 95 96 ```c++ 97 #include <IPCKit/ipc_kit.h> 98 99 static void OnNativeChildProcessStarted(int errCode, OHIPCRemoteProxy *remoteProxy) 100 { 101 if (errCode != NCP_NO_ERROR) { 102 // Exception handling when the child process is not started normally. 103 // ... 104 return; 105 } 106 107 // Save the remoteProxy object for IPC with the child process based on the APIs provided by IPC Kit. 108 // You are advised to transfer time-consuming operations to an independent thread to avoid blocking the callback thread for a long time. 109 // When the IPC object is no longer needed, call OH_IPCRemoteProxy_Destroy to release it. 110 // ... 111 } 112 ``` 113 114 The second parameter **OHIPCRemoteProxy** in the callback function is used to establish an IPC channel with the **OHIPCRemoteStub** object returned by the **NativeChildProcess_OnConnect** method implemented by the child process. For details, see [IPC Development (C/C++)](../ipc/ipc-capi-development-guideline.md). When the **OHIPCRemoteProxy** object is no longer needed, call [OH_IPCRemoteProxy_Destroy](../reference/apis-ipc-kit/_o_h_i_p_c_remote_object.md#oh_ipcremoteproxy_destroy) to release it. 115 1164. (Main process) Start the native child process. 117 118 Call the API to start the native child process. Note that the return value **NCP_NO_ERROR** only indicates that the native child process startup logic is successfully called. The actual startup result is asynchronously notified through the callback function specified in the second parameter. **A child process can be created only in the main process.** 119 120 ```c++ 121 #include <AbilityKit/native_child_process.h> 122 123 // The first parameter libchildprocesssample.so is the name of the dynamic link library that implements the necessary export functions of the child process. 124 int32_t ret = OH_Ability_CreateNativeChildProcess("libchildprocesssample.so", OnNativeChildProcessStarted); 125 if (ret != NCP_NO_ERROR) { 126 // Exception handling when the child process is not started normally. 127 // ... 128 } 129 ``` 130 1315. (Main process) Add build dependencies. 132 133 Modify the **CMaklist.txt** file to add the dependencies. The following assumes that the main process is implemented in the library file named **libmainprocesssample.so**. (The implementation of the main process and child processes can be compiled to the same dynamic link library file.) 134 135 ```txt 136 target_link_libraries(mainprocesssample PUBLIC 137 # Add dependencies of the dynamic link library of IPC Kit and Ability Kit. 138 libipc_capi.so 139 libchild_process.so 140 141 # Dependencies of other dynamic link libraries 142 # ... 143 ) 144 ``` 145 146## Creating a Child Process That Supports Pass-by-Parameter 147 148### When to Use 149 150This section describes how to create a native child process and pass parameters to it. 151 152### Available APIs 153 154| Name | Description | 155| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | 156| [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) | Starts a child process and returns its PID.| 157 158### How to Develop 159 160 161**Linking Dynamic Libraries** 162 163```txt 164libchild_process.so 165``` 166 167**Including Header Files** 168 169```c++ 170#include <AbilityKit/native_child_process.h> 171``` 172 1731. (Child process) Implement necessary export functions. 174 175 In the child process, implement and export the entry function [NativeChildProcess_Args](../reference/apis-ability-kit/c-apis-ability-childprocess.md#nativechildprocess_args). (It is assumed that the code file is named **ChildProcessSample.cpp**.) After the child process is started, the entry function is invoked. After the second function is returned, the child process exits. 176 177 ```c++ 178 #include <AbilityKit/native_child_process.h> 179 180 extern "C" { 181 182 /** 183 * Entry function of a child process, which implements the service logic of the child process. 184 * The function name can be customized and is specified when the main process calls the OH_Ability_StartNativeChildProcess method. In this example, the function name is Main. 185 * After the function is returned, the child process exits. 186 */ 187 void Main(NativeChildProcess_Args args) 188 { 189 // Obtain the input entryPrams. 190 char *entryParams = args.entryParams; 191 // Obtain the input FD list. 192 NativeChildProcess_Fd *current = args.fdList.head; 193 while (current != nullptr) { 194 char *fdName = current->fdName; 195 int32_t fd = current->fd; 196 current = current->next; 197 // Service logic 198 } 199 } 200 } // extern "C" 201 ``` 202 2032. (Child process) Compile a dynamic link library. 204 205 Modify the **CMakeList.txt** file, compile the file into a dynamic link library (named **libchildprocesssample.so** in this example), and add the dependency of the dynamic link library of Ability Kit. 206 207 ```txt 208 add_library(childprocesssample SHARED 209 # Source code file that implements the necessary export functions 210 ChildProcessSample.cpp 211 212 # Other source code files 213 # ... 214 ) 215 216 target_link_libraries(childprocesssample PUBLIC 217 # Add the dependency of the dynamic link library of Ability Kit. 218 libchild_process.so 219 220 # Dependencies of other dynamic link libraries 221 # ... 222 ) 223 ``` 224 2253. (Main process) Start the native child process. 226 227 Call the API to start the native child process. The return value **NCP_NO_ERROR** indicates that the native child process is successfully started. 228 229 ```c++ 230 #include <AbilityKit/native_child_process.h> 231 #include <stdlib.h> 232 #include <string.h> 233 #include <fcntl.h> 234 235 void startNativeChildProcess() 236 { 237 // ... 238 NativeChildProcess_Args args; 239 // Set entryParams. The maximum amount of data that can be passed is 150 KB. 240 args.entryParams = (char*)malloc(sizeof(char) * 10); 241 (void)strcpy(args.entryParams, "testParam"); 242 243 // Insert a node to the head node of the linked list. 244 args.fdList.head = (NativeChildProcess_Fd*)malloc(sizeof(NativeChildProcess_Fd)); 245 // FD keyword, which contains a maximum of 20 characters. 246 args.fdList.head->fdName = (char*)malloc(sizeof(char) * 4); 247 (void)strcpy(args.fdList.head->fdName, "fd1"); 248 // Obtain the FD logic. 249 int32_t fd = open("/data/storage/el2/base/haps/entry/files/test.txt", O_RDWR | O_CREAT, 0644); 250 args.fdList.head->fd = fd; 251 // Insert only one FD record. You can insert a maximum of 16 FD records to the linked list as required. 252 args.fdList.head->next = NULL; 253 NativeChildProcess_Options options = { 254 .isolationMode = NCP_ISOLATION_MODE_ISOLATED 255 }; 256 257 // The first parameter libchildprocesssample.so:Main indicates the name of the dynamic link library file that implements the Main method of the child process and the name of the entry method. 258 int32_t pid = -1; 259 Ability_NativeChildProcess_ErrCode ret = OH_Ability_StartNativeChildProcess( 260 "libchildprocesssample.so:Main", args, options, &pid); 261 if (ret != NCP_NO_ERROR) { 262 // Release the memory space in NativeChildProcess_Args to prevent memory leakage. 263 // Exception handling when the child process is not started normally. 264 // ... 265 } 266 267 // Other logic 268 // ... 269 270 // Release the memory space in NativeChildProcess_Args to prevent memory leakage. 271 } 272 ``` 273 2744. (Main process) Add build dependencies. 275 276 Modify the **CMaklist.txt** file to add the dependencies. The following assumes that the main process is implemented in the library file named **libmainprocesssample.so**. (The implementation of the main process and child processes can be compiled to the same dynamic link library file.) 277 278 ```txt 279 target_link_libraries(mainprocesssample PUBLIC 280 # Add the dependency of the dynamic link library of Ability Kit. 281 libchild_process.so 282 283 # Dependencies of other dynamic link libraries 284 # ... 285 ) 286 ``` 287