This content originally appeared on DEV Community and was authored by Asher
HarmonyOS Next Multiprocess Programming: Practice of Creating Child Processes and Inter – Process Communication
I. Overview of Child Process Creation in HarmonyOS Next
In the HarmonyOS Next operating system, processes serve as the basic units for system resource allocation. This module provides two methods for creating child processes, allowing developers to select appropriate approaches based on specific requirements:
- Creating child processes with IPC callback support: Suitable for scenarios where frequent communication between parent and child processes is needed.
- Creating child processes with parameter passing support: Suitable for scenarios requiring data or file descriptor transmission to child processes.
These two methods have distinct characteristics, and developers should make selections based on application architecture and functional requirements.
II. Creating Child Processes with IPC Callback Support
2.1 Scenario Introduction
This approach is applicable to scenarios where a stable communication channel needs to be established between parent and child processes. Through the IPC (Inter – Process Communication) mechanism, the parent process can communicate bidirectionally with the child process to implement complex collaborative logic.
Important Notes:
- Currently only supports 2in1 devices.
- Starting from API version 15, a single process supports up to 50 Native child processes.
- In API version 14 and earlier, a single process can only start 1 Native child process.
- Depends on IPCKit.
2.2 Detailed Development Steps
2.2.1 Preparation
Required dynamic library files:
-
libipc_capi.so
: IPC basic capability library. -
libchild_process.so
: Child process basic capability library.
Required header files:
#include <IPCKit/ipc_kit.h>
#include <AbilityKit/native_child_process.h>
2.2.2 Child Process Implementation
The child process needs to implement two key export functions:
extern "C" {
// Obtain the IPC Stub object for receiving IPC messages from the main process
OHIPCRemoteStub* NativeChildProcess_OnConnect()
{
// Implement IPC communication logic
return ipcRemoteStub;
}
// Main business logic of the child process
void NativeChildProcess_MainProc()
{
// Implement the core business of the child process
// The child process exits after the function returns
}
}
Compilation configuration: Modify CMakeLists.txt to add dependencies:
add_library(childprocesssample SHARED
ChildProcessSample.cpp
# Other source files
)
target_link_libraries(childprocesssample PUBLIC
libipc_capi.so
# Other dependent libraries
)
2.2.3 Main Process Implementation
Callback function implementation:
static void OnNativeChildProcessStarted(int errCode, OHIPCRemoteProxy *remoteProxy)
{
if (errCode != NCP_NO_ERROR) {
// Error handling
return;
}
// Save remoteProxy for subsequent IPC communication
// Note: The callback executes in a separate thread; avoid time - consuming operations
}
Start the child process:
int32_t ret = OH_Ability_CreateNativeChildProcess(
"libchildprocesssample.so",
OnNativeChildProcessStarted
);
if (ret != NCP_NO_ERROR) {
// Handle startup failure
}
Compilation configuration:
target_link_libraries(mainprocesssample PUBLIC
libipc_capi.so
libchild_process.so
# Other dependent libraries
)
2.3 Key Precautions
- Thread safety: The callback function executes in a separate thread, so thread synchronization should be noted.
-
Resource release: After using IPC objects, call
OH_IPCRemoteProxy_Destroy
to release them. - Performance considerations: Avoid executing time – consuming operations in the callback.
III. Creating Child Processes with Parameter Passing Support
3.1 Scenario Introduction
This approach is suitable for scenarios where initialization parameters or file descriptors need to be passed to child processes, such as transmitting configuration data or shared resources.
3.2 Detailed Development Steps
3.2.1 Child Process Implementation
Entry function implementation:
extern "C" {
void Main(NativeChildProcess_Args args)
{
// Get string parameters
char *entryParams = args.entryParams;
// Process the file descriptor list
NativeChildProcess_Fd *current = args.fdList.head;
while (current != nullptr) {
char *fdName = current->fdName;
int32_t fd = current->fd;
// Business logic processing
current = current->next;
}
}
}
Compilation configuration:
add_library(childprocesssample SHARED
ChildProcessSample.cpp
# Other source files
)
target_link_libraries(childprocesssample PUBLIC
libchild_process.so
# Other dependent libraries
)
3.2.2 Main Process Implementation
Parameter setting:
NativeChildProcess_Args args;
// Set string parameters (up to 150KB)
args.entryParams = (char*)malloc(sizeof(char) * 10);
strcpy(args.entryParams, "testParam");
// Set file descriptors
args.fdList.head = (NativeChildProcess_Fd*)malloc(sizeof(NativeChildProcess_Fd));
args.fdList.head->fdName = (char*)malloc(sizeof(char) * 4);
strcpy(args.fdList.head->fdName, "fd1");
args.fdList.head->fd = open("/data/storage/.../test.txt", O_RDWR | O_CREAT, 0644);
args.fdList.head->next = NULL;
NativeChildProcess_Options options = {
.isolationMode = NCP_ISOLATION_MODE_ISOLATED
};
int32_t pid = -1;
Ability_NativeChildProcess_ErrCode ret = OH_Ability_StartNativeChildProcess(
"libchildprocesssample.so:Main",
args,
options,
&pid
);
Memory management:
- Release the memory space in
NativeChildProcess_Args
after use. - Prevent memory leaks.
3.3 Child Process Obtaining Startup Parameters
Starting from API version 17, child processes can obtain their own startup parameters:
extern "C" {
void ThreadFunc()
{
NativeChildProcess_Args *args = OH_Ability_GetCurrentChildProcessArgs();
if (args == nullptr) return;
// Use the parameters...
}
void Main(NativeChildProcess_Args args)
{
// Create a thread to access the parameters
std::thread tObj(ThreadFunc);
}
}
IV. Best Practices and Precautions
4.1 Best Practices for Process Creation
-
Reasonably select the creation method:
- For frequent communication → Choose the IPC callback method.
- For data transmission → Choose the parameter passing method.
-
Resource management:
- Release unused resources in a timely manner.
- Pay attention to the life cycle management of file descriptors.
-
Error handling:
- Check the return values of all API calls.
- Implement comprehensive error handling logic.
4.2 Performance Optimization Suggestions
-
Control the number of child processes:
- Avoid creating too many child processes, which may lead to tight system resources.
- Consider using the process pool pattern.
-
Communication efficiency:
- For the IPC callback method, optimize the message structure and communication frequency.
- Consider batch data transmission to reduce the number of communications.
-
Memory usage:
- Note the memory copy overhead during parameter passing.
- For large data, consider using the shared memory mechanism.
4.3 Security Considerations
-
Parameter verification:
- Strictly verify the passed parameters.
- Prevent injection attacks.
-
Permission control:
- Child processes should follow the principle of least privilege.
- Sensitive operations should be completed in the main process.
-
Resource isolation:
- Reasonably set the isolation mode.
- Avoid child processes affecting the stability of the main process.
V. Summary
HarmonyOS Next provides a flexible child process creation mechanism, allowing developers to select appropriate methods based on specific needs:
- The IPC callback method is suitable for scenarios requiring complex interactions but has a higher implementation complexity.
- The parameter passing method is suitable for simple data transmission needs and is relatively easy to implement.
Regardless of the chosen method, attention should be paid to resource management, error handling, and performance optimization. By reasonably using multiprocessing technology, the stability, security, and performance of applications can be significantly improved.
With the continuous development of HarmonyOS Next, its multiprocess programming model will become more perfect, providing developers with more powerful system – level support. It is recommended that developers deeply understand the relevant APIs and best practices to build efficient and reliable multiprocess application architectures.
This content originally appeared on DEV Community and was authored by Asher