1# Creating Native Child Processes (C/C++) 2<!--Kit: Ability Kit--> 3<!--Subsystem: Ability--> 4<!--Owner: @SKY2001--> 5<!--Designer: @jsjzju--> 6<!--Tester: @lixueqing513--> 7<!--Adviser: @huipeizi--> 8 9You can create a child process in either of the following ways: 10- [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). 11- [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. 12 13 14## Creating a Child Process That Supports IPC Callback 15 16### When to Use 17 18This 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. 19 20### Available APIs 21 22| Name | Description | 23| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | 24| int [OH_Ability_CreateNativeChildProcess](../reference/apis-ability-kit/capi-native-child-process-h.md#oh_ability_createnativechildprocess) (const char *libName, [OH_Ability_OnNativeChildProcessStarted](../reference/apis-ability-kit/capi-native-child-process-h.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.| 25 26> **NOTE** 27> 28> Starting from API version 14, 2-in-1 devices and tablets are supported. In API version 13 and earlier versions, only 2-in-1 devices are supported. 29> 30> Starting from 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. 31 32### How to Develop 33 34This 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. 35 36**Linking Dynamic Libraries** 37 38```txt 39libipc_capi.so 40libchild_process.so 41``` 42 43**Including Header Files** 44 45```c++ 46#include <IPCKit/ipc_kit.h> 47#include <AbilityKit/native_child_process.h> 48``` 49 501. (Child process) Implement necessary export functions. 51 52 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). 53 54 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. 55 56 ```c++ 57 #include <IPCKit/ipc_kit.h> 58 59 extern "C" { 60 61 OHIPCRemoteStub* NativeChildProcess_OnConnect() 62 { 63 // 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. 64 // The child process controls its lifecycle according to the service logic. 65 return ipcRemoteStub; 66 } 67 68 void NativeChildProcess_MainProc() 69 { 70 // Equivalent to the Main function of the child process. It implements the service logic of the child process. 71 // ... 72 // After the function is returned, the child process exits. 73 } 74 75 } // extern "C" 76 ``` 77 782. (Child process) Compile a dynamic link library. 79 80 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. 81 82 ```txt 83 add_library(childprocesssample SHARED 84 # Source code file that implements the necessary export functions 85 ChildProcessSample.cpp 86 87 # Other source code files 88 # ... 89 ) 90 91 target_link_libraries(childprocesssample PUBLIC 92 # Add the dependency of the dynamic link library of IPC Kit. 93 libipc_capi.so 94 95 # Dependencies of other dynamic link libraries 96 # ... 97 ) 98 ``` 99 1003. (Main process) Implement the child process startup result callback. 101 102 ```c++ 103 #include <IPCKit/ipc_kit.h> 104 105 static void OnNativeChildProcessStarted(int errCode, OHIPCRemoteProxy *remoteProxy) 106 { 107 if (errCode != NCP_NO_ERROR) { 108 // Exception handling when the child process is not started normally. 109 // ... 110 return; 111 } 112 113 // Save the remoteProxy object for IPC with the child process based on the APIs provided by IPC Kit. 114 // You are advised to transfer time-consuming operations to an independent thread to avoid blocking the callback thread for a long time. 115 // When the IPC object is no longer needed, call OH_IPCRemoteProxy_Destroy to release it. 116 // ... 117 } 118 ``` 119 120 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/capi-ipc-cremote-object-h.md#oh_ipcremoteproxy_destroy) to release it. 121 1224. (Main process) Start the native child process. 123 124 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.** 125 126 ```c++ 127 #include <AbilityKit/native_child_process.h> 128 129 // The first parameter libchildprocesssample.so is the name of the dynamic link library that implements the necessary export functions of the child process. 130 int32_t ret = OH_Ability_CreateNativeChildProcess("libchildprocesssample.so", OnNativeChildProcessStarted); 131 if (ret != NCP_NO_ERROR) { 132 // Exception handling when the child process is not started normally. 133 // ... 134 } 135 ``` 136 1375. (Main process) Add build dependencies. 138 139 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.) 140 141 ```txt 142 target_link_libraries(mainprocesssample PUBLIC 143 # Add dependencies of the dynamic link library of IPC Kit and Ability Kit. 144 libipc_capi.so 145 libchild_process.so 146 147 # Dependencies of other dynamic link libraries 148 # ... 149 ) 150 ``` 151 152## Creating a Child Process That Supports Pass-by-Parameter 153 154### When to Use 155 156This section describes how to create a native child process and pass parameters to it. 157 158### Available APIs 159 160| Name | Description | 161| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | 162| [Ability_NativeChildProcess_ErrCode](../reference/apis-ability-kit/capi-native-child-process-h.md#ability_nativechildprocess_errcode) [OH_Ability_StartNativeChildProcess](../reference/apis-ability-kit/capi-native-child-process-h.md#oh_ability_startnativechildprocess) (const char \*entry, [NativeChildProcess_Args](../reference/apis-ability-kit/capi-nativechildprocess-args.md) args, [NativeChildProcess_Options](../reference/apis-ability-kit/capi-nativechildprocess-options.md) options, int32_t *pid) | Starts a child process and returns its PID.| 163 164### How to Develop 165 166 167**Linking Dynamic Libraries** 168 169```txt 170libchild_process.so 171``` 172 173**Including Header Files** 174 175```c++ 176#include <AbilityKit/native_child_process.h> 177``` 178 1791. (Child process) Implement necessary export functions. 180 181 In the child process, implement and export the entry function [NativeChildProcess_Args](../reference/apis-ability-kit/capi-nativechildprocess-args.md). (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. 182 183 ```c++ 184 #include <AbilityKit/native_child_process.h> 185 186 extern "C" { 187 188 /** 189 * Entry function of a child process, which implements the service logic of the child process. 190 * 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. 191 * After the function is returned, the child process exits. 192 */ 193 void Main(NativeChildProcess_Args args) 194 { 195 // Obtain the input entryPrams. 196 char *entryParams = args.entryParams; 197 // Obtain the input FD list. 198 NativeChildProcess_Fd *current = args.fdList.head; 199 while (current != nullptr) { 200 char *fdName = current->fdName; 201 int32_t fd = current->fd; 202 current = current->next; 203 // Service logic 204 } 205 } 206 } // extern "C" 207 ``` 208 2092. (Child process) Compile a dynamic link library. 210 211 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. 212 213 ```txt 214 add_library(childprocesssample SHARED 215 # Source code file that implements the necessary export functions 216 ChildProcessSample.cpp 217 218 # Other source code files 219 # ... 220 ) 221 222 target_link_libraries(childprocesssample PUBLIC 223 # Add the dependency of the dynamic link library of Ability Kit. 224 libchild_process.so 225 226 # Dependencies of other dynamic link libraries 227 # ... 228 ) 229 ``` 230 2313. (Main process) Start the native child process. 232 233 Call the API to start the native child process. The return value **NCP_NO_ERROR** indicates that the native child process is successfully started. 234 235 ```c++ 236 #include <AbilityKit/native_child_process.h> 237 #include <stdlib.h> 238 #include <string.h> 239 #include <fcntl.h> 240 241 void startNativeChildProcess() 242 { 243 // ... 244 NativeChildProcess_Args args; 245 // Set entryParams. The maximum amount of data that can be passed is 150 KB. 246 args.entryParams = (char*)malloc(sizeof(char) * 10); 247 (void)strcpy(args.entryParams, "testParam"); 248 249 // Insert a node to the head node of the linked list. 250 args.fdList.head = (NativeChildProcess_Fd*)malloc(sizeof(NativeChildProcess_Fd)); 251 // FD keyword, which contains a maximum of 20 characters. 252 args.fdList.head->fdName = (char*)malloc(sizeof(char) * 4); 253 (void)strcpy(args.fdList.head->fdName, "fd1"); 254 // Obtain the FD logic. 255 int32_t fd = open("/data/storage/el2/base/haps/entry/files/test.txt", O_RDWR | O_CREAT, 0644); 256 args.fdList.head->fd = fd; 257 // Insert only one FD record. You can insert a maximum of 16 FD records to the linked list as required. 258 args.fdList.head->next = NULL; 259 NativeChildProcess_Options options = { 260 .isolationMode = NCP_ISOLATION_MODE_ISOLATED 261 }; 262 263 // 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. 264 int32_t pid = -1; 265 Ability_NativeChildProcess_ErrCode ret = OH_Ability_StartNativeChildProcess( 266 "libchildprocesssample.so:Main", args, options, &pid); 267 if (ret != NCP_NO_ERROR) { 268 // Release the memory space in NativeChildProcess_Args to prevent memory leakage. 269 // Exception handling when the child process is not started normally. 270 // ... 271 } 272 273 // Other logic 274 // ... 275 276 // Release the memory space in NativeChildProcess_Args to prevent memory leakage. 277 } 278 ``` 279 2804. (Main process) Add build dependencies. 281 282 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.) 283 284 ```txt 285 target_link_libraries(mainprocesssample PUBLIC 286 # Add the dependency of the dynamic link library of Ability Kit. 287 libchild_process.so 288 289 # Dependencies of other dynamic link libraries 290 # ... 291 ) 292 ``` 293 294## Child Threads Obtaining Startup Parameters 295 296### When to Use 297 298Starting from API version 17, child processes can obtain startup parameters. 299 300### Available APIs 301 302| Name | Description | 303| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | 304| [NativeChildProcess_Args](../reference/apis-ability-kit/capi-nativechildprocess-args.md)* [OH_Ability_GetCurrentChildProcessArgs](../reference/apis-ability-kit/capi-native-child-process-h.md#oh_ability_getcurrentchildprocessargs)() | Returns the startup parameters of the child process.| 305 306### How to Develop 307 308 309**Linking Dynamic Libraries** 310 311```txt 312libchild_process.so 313``` 314 315**Including Header Files** 316 317```c++ 318#include <AbilityKit/native_child_process.h> 319``` 320 321**Obtaining Startup Parameters** 322 323After a child process is created through [OH_Ability_StartNativeChildProcess](../reference/apis-ability-kit/capi-native-child-process-h.md#oh_ability_startnativechildprocess), it can call [OH_Ability_GetCurrentChildProcessArgs](../reference/apis-ability-kit/capi-native-child-process-h.md#oh_ability_getcurrentchildprocessargs)() to obtain the startup parameters [NativeChildProcess_Args](../reference/apis-ability-kit/capi-nativechildprocess-args.md) from any .so file or child thread, facilitating operations on related file descriptors. 324 325```c++ 326#include <AbilityKit/native_child_process.h> 327#include <thread> 328 329extern "C" { 330 331void ThreadFunc() 332{ 333 // Obtain the startup parameters of the child process. 334 NativeChildProcess_Args *args = OH_Ability_GetCurrentChildProcessArgs(); 335 // If the startup parameters fail to be obtained, nullptr is returned. 336 if (args == nullptr) { 337 return; 338 } 339 // Obtain the value of entryPrams in the startup parameters. 340 char *entryParams = args->entryParams; 341 // Obtain the FD list. 342 NativeChildProcess_Fd *current = args->fdList.head; 343 while (current != nullptr) { 344 char *fdName = current->fdName; 345 int32_t fd = current->fd; 346 current = current->next; 347 // Service logic 348 } 349} 350 351/** 352 * Entry function of a child process, which implements the service logic of the child process. 353 * args is the startup parameters of the child process. 354 */ 355void Main(NativeChildProcess_Args args) 356{ 357 // Service logic 358 359 // Create a thread. 360 std::thread tObj(ThreadFunc); 361} 362 363} // extern "C" 364``` 365