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> Currently, only 2-in-1 devices are supported, and only one native child process can be started for a process. 23 24### How to Develop 25 26This 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. 27 28**Linking Dynamic Libraries** 29 30```txt 31libipc_capi.so 32libchild_process.so 33``` 34 35**Including Header Files** 36 37```c++ 38#include <IPCKit/ipc_kit.h> 39#include <AbilityKit/native_child_process.h> 40``` 41 421. (Child process) Implement necessary export functions. 43 44 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). 45 46 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. 47 48 ```c++ 49 #include <IPCKit/ipc_kit.h> 50 51 extern "C" { 52 53 OHIPCRemoteStub* NativeChildProcess_OnConnect() 54 { 55 // 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. 56 // The child process controls its lifecycle according to the service logic. 57 return ipcRemoteStub; 58 } 59 60 void NativeChildProcess_MainProc() 61 { 62 // Equivalent to the Main function of the child process. It implements the service logic of the child process. 63 // ... 64 // After the function is returned, the child process exits. 65 } 66 67 } // extern "C" 68 ``` 69 702. (Child process) Compile a dynamic link library. 71 72 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. 73 74 ```txt 75 add_library(childprocesssample SHARED 76 # Source code file that implements the necessary export functions 77 ChildProcessSample.cpp 78 79 # Other source code files 80 # ... 81 ) 82 83 target_link_libraries(childprocesssample PUBLIC 84 # Add the dependency of the dynamic link library of IPC Kit. 85 libipc_capi.so 86 87 # Dependencies of other dynamic link libraries 88 # ... 89 ) 90 ``` 91 923. (Main process) Implement the child process startup result callback. 93 94 ```c++ 95 #include <IPCKit/ipc_kit.h> 96 97 static void OnNativeChildProcessStarted(int errCode, OHIPCRemoteProxy *remoteProxy) 98 { 99 if (errCode != NCP_NO_ERROR) { 100 // Exception handling when the child process is not started normally. 101 // ... 102 return; 103 } 104 105 // Save the remoteProxy object for IPC with the child process based on the APIs provided by IPC Kit. 106 // You are advised to transfer time-consuming operations to an independent thread to avoid blocking the callback thread for a long time. 107 // When the IPC object is no longer needed, call OH_IPCRemoteProxy_Destroy to release it. 108 // ... 109 } 110 ``` 111 112 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. 113 1144. (Main process) Start the native child process. 115 116 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.** 117 118 ```c++ 119 #include <AbilityKit/native_child_process.h> 120 121 // The first parameter libchildprocesssample.so is the name of the dynamic link library that implements the necessary export functions of the child process. 122 int32_t ret = OH_Ability_CreateNativeChildProcess("libchildprocesssample.so", OnNativeChildProcessStarted); 123 if (ret != NCP_NO_ERROR) { 124 // Exception handling when the child process is not started normally. 125 // ... 126 } 127 ``` 128 1295. (Main process) Add build dependencies. 130 131 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.) 132 133 ```txt 134 target_link_libraries(mainprocesssample PUBLIC 135 # Add dependencies of the dynamic link library of IPC Kit and Ability Kit. 136 libipc_capi.so 137 libchild_process.so 138 139 # Dependencies of other dynamic link libraries 140 # ... 141 ) 142 ``` 143 144## Creating a Child Process That Supports Pass-by-Parameter 145 146### When to Use 147 148This section describes how to create a native child process and pass parameters to it. 149 150### Available APIs 151 152| Name | Description | 153| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | 154| [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.| 155 156### How to Develop 157 158 159**Linking Dynamic Libraries** 160 161```txt 162libchild_process.so 163``` 164 165**Including Header Files** 166 167```c++ 168#include <AbilityKit/native_child_process.h> 169``` 170 1711. (Child process) Implement necessary export functions. 172 173 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. 174 175 ```c++ 176 #include <AbilityKit/native_child_process.h> 177 178 extern "C" { 179 180 /** 181 * Entry function of a child process, which implements the service logic of the child process. 182 * 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. 183 * After the function is returned, the child process exits. 184 */ 185 void Main(NativeChildProcess_Args args) 186 { 187 // Obtain the input entryPrams. 188 char *entryParams = args.entryParams; 189 // Obtain the input FD list. 190 NativeChildProcess_Fd *current = args.fdList.head; 191 while (current != nullptr) { 192 char *fdName = current->fdName; 193 int32_t fd = current->fd; 194 current = current->next; 195 // Service logic 196 } 197 } 198 } // extern "C" 199 ``` 200 2012. (Child process) Compile a dynamic link library. 202 203 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. 204 205 ```txt 206 add_library(childprocesssample SHARED 207 # Source code file that implements the necessary export functions 208 ChildProcessSample.cpp 209 210 # Other source code files 211 # ... 212 ) 213 214 target_link_libraries(childprocesssample PUBLIC 215 # Add the dependency of the dynamic link library of Ability Kit. 216 libchild_process.so 217 218 # Dependencies of other dynamic link libraries 219 # ... 220 ) 221 ``` 222 2233. (Main process) Start the native child process. 224 225 Call the API to start the native child process. The return value **NCP_NO_ERROR** indicates that the native child process is successfully started. 226 227 ```c++ 228 #include <AbilityKit/native_child_process.h> 229 #include <stdlib.h> 230 #include <string.h> 231 #include <fcntl.h> 232 233 void startNativeChildProcess() 234 { 235 // ... 236 NativeChildProcess_Args args; 237 // Set entryParams. The maximum amount of data that can be passed is 150 KB. 238 args.entryParams = (char*)malloc(sizeof(char) * 10); 239 (void)strcpy(args.entryParams, "testParam"); 240 241 // Insert a node to the head node of the linked list. 242 args.fdList.head = (NativeChildProcess_Fd*)malloc(sizeof(NativeChildProcess_Fd)); 243 // FD keyword, which contains a maximum of 20 characters. 244 args.fdList.head->fdName = (char*)malloc(sizeof(char) * 4); 245 (void)strcpy(args.fdList.head->fdName, "fd1"); 246 // Obtain the FD logic. 247 int32_t fd = open("/data/storage/el2/base/haps/entry/files/test.txt", O_RDWR | O_CREAT, 0644); 248 args.fdList.head->fd = fd; 249 // Insert only one FD record. You can insert a maximum of 16 FD records to the linked list as required. 250 args.fdList.head->next = NULL; 251 NativeChildProcess_Options options = { 252 .isolationMode = NCP_ISOLATION_MODE_ISOLATED 253 }; 254 255 // 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. 256 int32_t pid = -1; 257 Ability_NativeChildProcess_ErrCode ret = OH_Ability_StartNativeChildProcess( 258 "libchildprocesssample.so:Main", args, options, &pid); 259 if (ret != NCP_NO_ERROR) { 260 // Release the memory space in NativeChildProcess_Args to prevent memory leakage. 261 // Exception handling when the child process is not started normally. 262 // ... 263 } 264 265 // Other logic 266 // ... 267 268 // Release the memory space in NativeChildProcess_Args to prevent memory leakage. 269 } 270 ``` 271 2724. (Main process) Add build dependencies. 273 274 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.) 275 276 ```txt 277 target_link_libraries(mainprocesssample PUBLIC 278 # Add the dependency of the dynamic link library of Ability Kit. 279 libchild_process.so 280 281 # Dependencies of other dynamic link libraries 282 # ... 283 ) 284 ``` 285