• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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