未验证 提交 507a32cf 编写于 作者: O openharmony_ci 提交者: Gitee

!11951 翻译已完成10514+10486+10397+10448

Merge pull request !11951 from shawn_he/10448-a
...@@ -2,17 +2,27 @@ ...@@ -2,17 +2,27 @@
## Overview ## Overview
### Basic Concepts ### Basic Concepts
- Introduction to begetctl - Introduction to begetctl
For details, see [Description of begetctl Commands](#table14737791480).
begetctl is a CLI-based management tool. For details about this functions, see [Description of begetctl Commands](#table14737791480).
- bootchart plug-in - bootchart plug-in
The bootchart plug-in is an open source tool used to evaluate system performance during Linux startup. It automatically collects information such as the CPU usage, disk throughput, and process status, and displays the evaluation result in graphics to facilitate system startup optimization. The bootchart plug-in is an open source tool used to evaluate system performance during Linux startup. It automatically collects information such as the CPU usage, disk throughput, and process status, and displays the evaluation result in graphics to facilitate system startup optimization.
- bootevent plug-in
bootevent is a plug-in that records key startup events of the init process and each service. The recorded information includes the event name, startup time of the service associated with the event, and event occurrence time. By using the exported file for trace parsing, you can then optimize the system startup process.
### Constraints ### Constraints
bootchart is available only for the standard system, and begetctl is available for both the small system and the standard system. bootchart and bootevent are available only for the standard system, and begetctl is available for both the small system and the standard system.
## How to Develop
## Development Guidelines
### Parameters ### Parameters
**Table 1** Description of begetctl commands<a name="table14737791480"></a> **Table 1** Description of begetctl commands<a name="table14737791480"></a>
| Command| Format and Example| Description| | Command| Format and Example| Description|
| :---------- | :---------- |:--------| | :---------- | :---------- |:--------|
...@@ -22,7 +32,7 @@ bootchart is available only for the standard system, and begetctl is available f ...@@ -22,7 +32,7 @@ bootchart is available only for the standard system, and begetctl is available f
| param set name value| Sets system parameters.<br>Example:<br>begetctl param set ohos.servicectrl.display 1 or param set ohos.servicectrl.display 1| N/A| | param set name value| Sets system parameters.<br>Example:<br>begetctl param set ohos.servicectrl.display 1 or param set ohos.servicectrl.display 1| N/A|
| param wait name [value] [timeout] | Waits for system parameters.<br>Example:<br>begetctl param wait persist.sys.usb.config hdc or param wait persist.sys.usb.config hdc| The default value of **timeout** is **30**.| | param wait name [value] [timeout] | Waits for system parameters.<br>Example:<br>begetctl param wait persist.sys.usb.config hdc or param wait persist.sys.usb.config hdc| The default value of **timeout** is **30**.|
| param dump [verbose] | Dumps system parameter information.<br>Example:<br>begetctl param dump or param dump| N/A| | param dump [verbose] | Dumps system parameter information.<br>Example:<br>begetctl param dump or param dump| N/A|
| param shell <i>[name]</i> | Enters the parameter shell.<br>Example:<br>begetctl param shell or param shell| N/A| | param shell [name] | Enters the parameter shell.<br>Example:<br>begetctl param shell or param shell| N/A|
| timer_stop servicename | Stops the service timer.<br>Example:<br>begetctl timer_stop appspawn | The value of **servicename** can contain a maximum of 96 characters.| | timer_stop servicename | Stops the service timer.<br>Example:<br>begetctl timer_stop appspawn | The value of **servicename** can contain a maximum of 96 characters.|
| timer_start servicename timeout | Starts the service timer.<br>Example:<br>begetctl timer_start appspawn | The value of **servicename** can contain a maximum of 96 characters. The default value of **timeout** is **10**. | | timer_start servicename timeout | Starts the service timer.<br>Example:<br>begetctl timer_start appspawn | The value of **servicename** can contain a maximum of 96 characters. The default value of **timeout** is **10**. |
| start_service servicename | Starts a service.<br>Example:<br>begetctl start_service appspawn or start_service appspawn| N/A| | start_service servicename | Starts a service.<br>Example:<br>begetctl start_service appspawn or start_service appspawn| N/A|
...@@ -54,21 +64,19 @@ bootchart is available only for the standard system, and begetctl is available f ...@@ -54,21 +64,19 @@ bootchart is available only for the standard system, and begetctl is available f
| modulectl uninstall moduleName | Uninstalls a dynamic plug-in.<br>Example:<br>modulectl uninstall bootchart | N/A| | modulectl uninstall moduleName | Uninstalls a dynamic plug-in.<br>Example:<br>modulectl uninstall bootchart | N/A|
| modulectl install moduleName | Installs a dynamic plug-in.<br>Example:<br>modulectl install bootchart | N/A| | modulectl install moduleName | Installs a dynamic plug-in.<br>Example:<br>modulectl install bootchart | N/A|
| modulectl list | Views the list of dynamic plug-ins.<br>Example:<br>begetctl modulectl list | N/A| | modulectl list | Views the list of dynamic plug-ins.<br>Example:<br>begetctl modulectl list | N/A|
| setloglevel level | Sets the log level to **info**.<br>Example:<br>begetctl setloglevel 1 | The log level ranges from **0** to **4**.|
| getloglevel | Obtains the log level of the init process.<br>Example:<br>begetctl getloglevel | N/A|
| bootevent disable | Disables the bootevent plug-in.<br>Example:<br>begetctl bootevent disable| N/A|
| bootevent enable | Enables the bootevent plug-in.<br>Example:<br>begetctl bootevent enable| N/A|
| dump_service parameter_service trigger | Displays information about all triggers.<br>Example:<br>begetctl dump_service parameter_service trigger | N/A|
| dump_service all | Displays information about all services.<br>Example:<br>begetctl dump_service all | N/A|
| dump_service serviceName | Displays information about a single service.<br>Example:<br>begetctl dump_service param_watcher | N/A|
| dump api | Displays information about APIs of the init process.<br>Example:<br>begetctl dump api | N/A|
## How to Develop
### Available APIs
**Table 1** Description of plug-in management APIs<a name="table14737791479"></a>
| API| Description|
| ---------- | ---------- |
| void PluginExecCmdByName(const char *name, const char *cmdContent) | Starts a plug-in by name.|
| void PluginExecCmdByCmdIndex(int index, const char *cmdContent) | Starts a plug-in by index.|
| int PluginExecCmd(const char *name, int argc, const char **argv) | Starts a plug-in by command.|
| int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd) | Adds the plug-in installation command.|
### How to Develop ### How to Develop
Add a plug-in. The following uses bootchart as an example: Add a plug-in. The following uses bootchart as an example:
1. Install the **.so** file and define an independent file to implement the following functions: 1. Install the **.so** file and define an independent file to implement the following functions:
```c ```c
static int bootchartEarlyHook(int stage, int prio, void *cookie) static int bootchartEarlyHook(int stage, int prio, void *cookie)
...@@ -87,11 +95,11 @@ bootchart is available only for the standard system, and begetctl is available f ...@@ -87,11 +95,11 @@ bootchart is available only for the standard system, and begetctl is available f
MODULE_CONSTRUCTOR(void) MODULE_CONSTRUCTOR(void)
{ {
// Depending on parameter service // Depends on parameter service
InitAddPostPersistParamLoadHook(0, bootchartEarlyHook); InitAddPostPersistParamLoadHook(0, bootchartEarlyHook);
} }
``` ```
2. Compile the static library **libbootchart_static** and add it to the **static_modules** group. 2. Compile the static library **libbootchart\_static** and add it to the **static\_modules** group.
``` ```
group("static_modules") { group("static_modules") {
if (!defined(ohos_lite)) { if (!defined(ohos_lite)) {
...@@ -138,19 +146,23 @@ bootchart is available only for the standard system, and begetctl is available f ...@@ -138,19 +146,23 @@ bootchart is available only for the standard system, and begetctl is available f
### Development Example ### Development Example
#### Bootchart
Prerequisites Prerequisites
1. Prepare the bootchart test environment. Specifically, install Python and pycairo by running **pip install pycairo** on Linux. 1. Prepare the bootchart test environment. Specifically, install Python and pycairo by running **pip install pycairo** on Linux.
2. Decompress **bootchart-master.tar**. 2. Decompress **bootchart-master.tar**.
tar -zxvf bootchart-master.tar tar -zxvf bootchart-master.tar
Procedure Procedure
1. Start the system. 1. Start the system.
2. Run the **begetctl bootchart enable** command. 2. Run the **begetctl bootchart enable** command.
3. Restart the system. 3. Restart the system.
4. Run the **begetctl bootchart stop** command. 4. Run the **begetctl bootchart stop** command.
5. Run the **begetctl bootchart disable** command. 5. Run the **begetctl bootchart disable** command.
6. Export the following files from the **/data/bootchart** directory and save them to the **bootchart** folder: 6. Export the following files from the **/data/bootchart** directory and save them to the **bootchart** folder:<br>
header<br> header<br>
proc_diskstats.log<br> proc_diskstats.log<br>
proc_ps.log<br> proc_ps.log<br>
...@@ -161,5 +173,38 @@ bootchart is available only for the standard system, and begetctl is available f ...@@ -161,5 +173,38 @@ bootchart is available only for the standard system, and begetctl is available f
python3 pybootchartgui.py -f pdf bootchart.tgz python3 pybootchartgui.py -f pdf bootchart.tgz
``` ```
Expected Result Expected result:
A **bootchart.pdf** file is generated in the **bootchart-master** directory. A **bootchart.pdf** file is generated in the **bootchart-master** directory.
#### bootevent
1. Configure one or more boot events in the **.cfg** file.
Configure a single boot event.
```json
bootevents : "bootevent.xxxbootevent",
```
Configure multiple boot events.
```json
bootevents : ["bootevent.xxxbootevent1", "bootevent.xxxbootevent2.xxx"],
```
> **NOTE**
>
> The configured event must start with **bootevent**.
2. Send the boot events.
Call the **SetParameter** API provided by init process to send the boot events. For example, to send the XXXbootevent1 event configured in the previous step, use the following code:
```c
SetParameter("bootevent.XXXbootevent1", "true");
```
3. Enable the bootevent function by running the **begetctl bootevent enable** command.
To disable the bootevent function, run the **begetctl bootevent disable** command and restart the system.
4. Use the exported bootevent file for trace analysis.
- The exported bootevent file is stored in the **/data/service/el0/startup/init/** directory.
- It is named in the format of *timestamp***.bootevent**.
- You can import the file to the trace analysis tool for visual analysis.
...@@ -7,7 +7,7 @@ The following figure shows the context structure of the Startup subsystem. ...@@ -7,7 +7,7 @@ The following figure shows the context structure of the Startup subsystem.
**Figure 1** Context structure of the Startup subsystem **Figure 1** Context structure of the Startup subsystem
![context-structure-of-the-startup-subsystem](figure/context-structure-of-the-Startup-subsystem.png) ![context-structure-of-the-Startup-subsystem](figure/context-structure-of-the-Startup-subsystem.png)
When the system is powered on, the kernel loads and starts services and applications as follows: When the system is powered on, the kernel loads and starts services and applications as follows:
...@@ -22,19 +22,24 @@ When the system is powered on, the kernel loads and starts services and applicat ...@@ -22,19 +22,24 @@ When the system is powered on, the kernel loads and starts services and applicat
The Startup subsystem consists of the following modules: The Startup subsystem consists of the following modules:
- init module<br> - init module
This module corresponds to the init process, which is the first user-mode process started after the kernel is initialized. After the init process starts, it reads and parses the **init.cfg** file. Based on the parsing result, the init module executes the commands listed in Table 2 in [Job Management](../subsystems/subsys-boot-init-jobs.md) and starts the key system service processes in sequence with corresponding permissions granted. This module corresponds to the init process, which is the first user-mode process started after the kernel is initialized. After the init process starts, it reads and parses the **init.cfg** file. Based on the parsing result, the init module executes the commands listed in Table 2 in [Job Management](../subsystems/subsys-boot-init-jobs.md) and starts the key system service processes in sequence with corresponding permissions granted.
- ueventd module<br> - ueventd module
This module listens for **netlink** events about hot swap of kernel device drivers and dynamically manages the **dev** node of the corresponding device based on the event type. This module listens for **netlink** events about hot swap of kernel device drivers and dynamically manages the **dev** node of the corresponding device based on the event type.
- appspawn module<br> - appspawn module
This module spawns application processes upon receiving commands from the foundation, configures permissions for new processes, and calls the entry function of the application framework. This module spawns application processes upon receiving commands from the foundation, configures permissions for new processes, and calls the entry function of the application framework.
- bootstrap module<br> - bootstrap module
This module provides entry identifiers for starting services and features. When SAMGR is started, the entry function identified by bootstrap is called and system services are started. This module provides entry identifiers for starting services and features. When SAMGR is started, the entry function identified by bootstrap is called and system services are started.
- syspara module<br> - syspara module
This module provides APIs for obtaining device information, such as the product name, brand name, and manufacturer name, based on the OpenHarmony Product Compatibility Specifications (PCS). It also provides APIs for setting and obtaining system attributes. This module provides APIs for obtaining device information, such as the product name, brand name, and manufacturer name, based on the OpenHarmony Product Compatibility Specifications (PCS). It also provides APIs for setting and obtaining system attributes.
...@@ -57,7 +62,9 @@ The Startup subsystem consists of the following modules: ...@@ -57,7 +62,9 @@ The Startup subsystem consists of the following modules:
- When porting a new chip platform, you need to add the **/vendor/etc/init/init.{hardware}.cfg** file that contains the platform-level initialization configuration. This file is used to implement platform-level initialization, for example, installing the ko driver and configuring information on the related **/proc** nodes. - When porting a new chip platform, you need to add the **/vendor/etc/init/init.{hardware}.cfg** file that contains the platform-level initialization configuration. This file is used to implement platform-level initialization, for example, installing the ko driver and configuring information on the related **/proc** nodes.
> **NOTE**: The configuration file **init.cfg** must be in JSON format. > **NOTE**
>
> The configuration file **init.cfg** must be in JSON format.
- bootstrap module: The zInit code must be configured in the link script. - bootstrap module: The zInit code must be configured in the link script.
...@@ -186,7 +193,9 @@ On each development board, you need to partition the memory to store the precedi ...@@ -186,7 +193,9 @@ On each development board, you need to partition the memory to store the precedi
This example assumes the **system** partition as the required partition on the Hi3516D V300 platform to illustrate the boot process. During this process, the init process reads the required fstab information, creates a block device node, and mounts it to the required partition. The following provides the key code snippets and log information as reference for debugging. This example assumes the **system** partition as the required partition on the Hi3516D V300 platform to illustrate the boot process. During this process, the init process reads the required fstab information, creates a block device node, and mounts it to the required partition. The following provides the key code snippets and log information as reference for debugging.
> **NOTE**: The code snippets below are exhibited in the logical sequence. They are not neighboring to each other in the source code. > **NOTE**
>
> The code snippets below are exhibited in the logical sequence. They are not neighboring to each other in the source code.
1. Obtain required device information. 1. Obtain required device information.
``` ```
...@@ -276,10 +285,11 @@ On each development board, you need to partition the memory to store the precedi ...@@ -276,10 +285,11 @@ On each development board, you need to partition the memory to store the precedi
``` ```
The key variables in the code are as follows: The key variables in the code are as follows:
**bus**: a string that saves the path of the bus connected to the current device. - **bus**: a string that saves the path of the bus connected to the current device.
**parent**: a string that stores the device path obtained from **syspath** in the uevent message. - **parent**: a string that stores the device path obtained from **syspath** in the uevent message.
**links**: a pointer to the memory that stores the soft link path. - **links**: a pointer to the memory that stores the soft link path.
**bootDevice**: a string that stores the value of **default_boot_device** in **bootargs** - **bootDevice**: a string that stores the value of **default_boot_device** in **bootargs**
According to the code, the corresponding soft link is created for the device only when the type of the connected bus is **platform**. The path of the soft link is as follows: According to the code, the corresponding soft link is created for the device only when the type of the connected bus is **platform**. The path of the soft link is as follows:
``` ```
/dev/block/platform/soc/10100000.himci.eMMC/by-name /dev/block/platform/soc/10100000.himci.eMMC/by-name
...@@ -328,13 +338,141 @@ On each development board, you need to partition the memory to store the precedi ...@@ -328,13 +338,141 @@ On each development board, you need to partition the memory to store the precedi
- Mounting of vendor partitions - Mounting of vendor partitions
After mounting required partitions, the init process scans each script file in the **vendor** partition. The initialization scripts related to the chip or development board are named in the format of **/vendor/etc/init.{ohos.boot.hardware}.cfg**. Wherein, **/vendor/etc/fstab.{ohos.boot.hardware}** represents the extended mount partition file; **hardware** is sourced from **bootargs**, which is passed from the bootloader to the kernel. After mounting required partitions, the init process scans each script file in the **vendor** partition. The initialization scripts related to the chip or development board are named in the format of **/vendor/etc/init.{ohos.boot.hardware}.cfg**. Wherein, **/vendor/etc/fstab.{ohos.boot.hardware}** represents the extended mount partition file; **hardware** is sourced from **bootargs**, which is passed from the bootloader to the kernel.
### Boot Loading Without ramdisk ### Boot Loading Without ramdisk
Certain development boards do not use the ramdisk boot mode. For these boards, the boot process is implemented by directly loading the **system.img** file through the kernel. In such case, you need to modify the product configuration file in **productdefine**. Specifically, you need to turn off the **enable_ramdisk** switch to disable ramdisk generation so that the init process does not boot from ramdisk to system. Certain development boards do not use the ramdisk boot mode. For these boards, the boot process is implemented by directly loading the **system.img** file through the kernel. In such case, you need to modify the product configuration file in **productdefine**. Specifically, you need to turn off the **enable_ramdisk** switch to disable ramdisk generation so that the init process does not boot from ramdisk to system.
The boot loading process in this scenario is similar to that in the preceding section. The only difference is as follows: If ramdisk is used, the init process mounts **system.img** to the **/usr** directory, and then switches to the **/usr** directory using **chroot** and executes the **/etc/init.cfg** script. If ramdisk is not used, there is no chroot process, and the boot script is **init.without_two_stages.cfg**. Boot loading in this scenario is similar to that in the preceding section. The only difference is as follows: If ramdisk is used, the init process mounts **system.img** to the **/usr** directory and then switches to the **/usr** directory using **chroot**. If ramdisk is not used, the init process directly runs the **init.cfg** file.
For boot loading without ramdisk (that is, system as root), the block device where the root file system is located is passed to the kernel through **bootargs**, for example, **root=/dev/mmcblk0p5 and rootfstype=ext4**. During initialization of the root file system, the kernel parses the **root** field in **bootargs** to complete mounting of the root file system.
### Partition A/B Booting
Currently, OpenHarmony supports booting from partitions A and B (active and standby system partitions), both of which are configured in the same device storage. During the booting process, the system partition to load is determined based on the slot of the active partition. Partition A/B booting is supported only for the system partition and chipset partition.
- bootslots
Number of the supported boot partitions. If **bootslots** is set to **2**, the system can boot from both system partitions A and B. If **bootslots** is set to **1**, partition A/B booting is not supported and the system can boot only from the default system partition.
In the initial phase of init process startup, the system reads the **bootslots** value to determine whether partition A/B booting is supported. If yes, the system continues to determine the system partition to mount. If not, the system mounts the system partition based on the default fstab. The API for the init process to obtain the **bootslots** value is as follows:
```
int GetBootSlots(void)
{
int bootSlots = GetSlotInfoFromParameter("bootslots");
BEGET_CHECK_RETURN_VALUE(bootSlots <= 0, bootSlots);
BEGET_LOGI("No valid slot value found from parameter, try to get it from cmdline");
return GetSlotInfoFromCmdLine("bootslots");
}
```
After normal system startup, you can obtain the **bootslots** value from the system parameter **ohos.boot.bootslots** to check whether the current system supports partition A/B booting. The command for obtaining **ohos.boot.bootslots** is as follows:
```
param get ohos.boot.bootslots
```
- currentslot
Current system partition, for example, partition A or partition B. The value of **currentslot** is a number. For example, **1** indicates partition A, and **2** indicates partition B.
In the initial phase of startup, the init process determines whether the system supports partition A/B booting based on **bootslots**. If the system does not support partition A/B booting, the init process directly boots from the default system partition instead of obtaining the **currentslot** value. If the system supports partition A/B booting, the init process obtains the **currentslot** value and determines whether partition A or partition B is the current system partition. The API for the init process to obtain the **currentslot** value is as follows:
```
int GetCurrentSlot(void)
{
// get current slot from parameter
int currentSlot = GetSlotInfoFromParameter("currentslot");
BEGET_CHECK_RETURN_VALUE(currentSlot <= 0, currentSlot);
BEGET_LOGI("No valid slot value found from parameter, try to get it from cmdline");
// get current slot from cmdline
currentSlot = GetSlotInfoFromCmdLine("currentslot");
BEGET_CHECK_RETURN_VALUE(currentSlot <= 0, currentSlot);
BEGET_LOGI("No valid slot value found from cmdline, try to get it from misc");
// get current slot from misc
return GetSlotInfoFromMisc(MISC_PARTITION_ACTIVE_SLOT_OFFSET, MISC_PARTITION_ACTIVE_SLOT_SIZE);
}
```
- Partition A/B booting process
1. Obtain the **currentslot** value to determine whether partition A or partition B is the current system partition.
2. Construct new partition mounting configuration based on the original fstab file, and add the suffix **a** or **b** to the partitions that support partition A/B booting, that is, system and chipset partitions.
3. Mount the partition added with the corresponding suffix and enter the second phase of startup. This phase occurs in partition A or B and concludes the partition A/B booting process.
The API for constructing new partition mounting configuration is as follows:
```
static void AdjustPartitionNameByPartitionSlot(FstabItem *item)
{
BEGET_CHECK_ONLY_RETURN(strstr(item->deviceName, "/system") != NULL ||
strstr(item->deviceName, "/chipset") != NULL);
char buffer[MAX_BUFFER_LEN] = {0};
int slot = GetCurrentSlot();
BEGET_ERROR_CHECK(slot > 0 && slot <= MAX_SLOT, slot = 1, "slot value %d is invalid, set default value", slot);
BEGET_INFO_CHECK(slot > 1, return, "default partition doesn't need to add suffix");
BEGET_ERROR_CHECK(sprintf_s(buffer, sizeof(buffer), "%s_%c", item->deviceName, 'a' + slot - 1) > 0,
return, "Failed to format partition name suffix, use default partition name");
free(item->deviceName);
item->deviceName = strdup(buffer);
BEGET_LOGI("partition name with slot suffix: %s", item->deviceName);
}
```
- Development example
The following uses the rk3568 platform as an example to illustrate how to change from default partition booting to partition A/B booting.
1. Burn the original image, and view the device information of each partition.
![Original partition](figure/ABStartup_1.png)
Use the original image to construct images of the partitions used for partition A/B booting, and test the partition A/B booting function.
- Copy the **system** and **vendor** images, and add the suffix **\_b** to them.
- Add partitions **system_b** and **vendor_b** to the partition table in **parameter.txt**.
2. Burn the images of the partitions used for partition A/B booting.
- Import the partition configuration to the rk3568 burning tool, and select the **parameter.txt** file containing the **system_b** and **vendor_b** partitions.
- Select images (including **system_b** and **vendor_b** images) based on the new partition table configuration, and then burn the images.
3. After the configuration is complete, perform the following:
1. Run the **cat /proc/cmdline** command. If the command output contains **bootslot=2**, the system supports partition A/B booting.
![cmdline](figure/ABStartup_2.png)
2. Run the **param get ohos.boot.bootslot** command. If the command output contains **2**, the **bootslot** information is successfully written to the **parameter.txt**.
3. Run the **ls -l /dev/block/by-name** command. If the command output contains **system_b** and **vendor_b**, device nodes are successfully created in partition B.
![Device information](figure/ABStartup_3.png)
4. Run the **df -h** command to check the partitions mounted to the system.
![Partition information](figure/ABStartup_4.png)
As shown in the figure, partition **mmcblk0p6** is mounted to the root file system (represented by a slash), and partition **mmcblk0p7** is mounted to **/vendor**. Based on the command output in step 3, **mmcblk0p6** is the **system** partition, and **mmcblk0p7** is the **vendor** partition. That is, the mounted partitions are the default partitions, that is, **system** and **vendor** partitions without suffixes. In other words, partition A is the default partition.
Next, let's try booting from partition B.
1) Run the **partitionslot setactive 2** command to set the slot of the active partition to **2**, that is, the slot of partition B.
![Partition slot configuration](figure/ABStartup_5.png)
2) Run the **partitionslot getslot** command to check the configured slot.
![View Slot](figure/ABStartup_6.png)
If **current slot** is **2**, the slot of the active partition is successfully set to **2**.
3) Upon restarting, run the **df -h** command to check the partitions mounted to the system.
According to the command output, partition **mmcblk0p11** is mounted to the root file system, and partition **mmcblk0p12** is mounted to **/vendor**.
![Mounting information](figure/ABStartup_7.png)
4) Run the **ls -l /dev/block/by-name** command again.
![New device information](figure/ABStartup_8.png)
For the boot loading process without ramdisk, that is, system as root, the block device where the root file system is located is passed to the kernel through **bootargs**, for example, **root=/dev/mmcblk0p5 and rootfstype=ext4**. During initialization of the root file system, the kernel parses the **root** field in **bootargs** to complete mounting of the root file system. **mmcblk0p11** corresponds to **system_b**, and **mmcblk0p12** corresponds to **vendor_b**. That is, the system is successfully booted from partition B.
# HiTraceMeter
## Introduction
HiTraceMeter is the OpenHarmony subsystem that provides APIs to implement call chain trace throughout a service process. With HiTraceMeter, you can quickly obtain the run log specific to the call chain of a service process and locate faults in inter-device, inter-process, or inter-thread communications. HiTraceMeter supports event logging in user mode and can collect trace data in user mode and kernel mode for performance tracing and analysis.
## Basic Concepts
The HiTraceMeter subsystem consists of three parts:
- JS/C++ HiTraceMeter APIs for application logging
- hitrace CLI tool for data collection
- smartperf tool for graphical data analysis
Wherein, HiTraceMeter APIs and the hitrace CLI tool run on the device side, and the smartperf tool runs on the PC side.
HiTraceMeter APIs are provided in C++ and JS for event logging, which aims to generate the trace data necessary for performance tracing and analysis during the development process.
The hitrace CLI tool is used to collect trace data. It captures trace data flows and saves the data as a text file.
The smartperf tool allows you to perform data analysis manually or use the analysis script for automated data analysis. If you want to get the data analysis done automatically, you need to supply the data file generated by the hitrace CLI tool as the input for the smartperf tool.
Traces data is classified by trace tag or trace category. Generally, one device subsystem corresponds to one tag. The tag is passed as the **Tag** parameter to event logging APIs. When you use the hitrace CLI tool to collect trace data, only the trace data specified by the **Tag** parameter is collected. Trace data of applications is fixedly labeled as **APP Tag**, and therefore, no **Tag** parameter needs to be passed to JS APIs. The following is a list of trace tags supported by HiTraceMeter. You can view the tags in [hitrace_meter.h](https://gitee.com/openharmony/hiviewdfx_hitrace/blob/master/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h).
```cpp
constexpr uint64_t HITRACE_TAG_NEVER = 0; // This tag is never enabled.
constexpr uint64_t HITRACE_TAG_ALWAYS = (1ULL << 0); // This tag is always enabled.
constexpr uint64_t HITRACE_TAG_DLP_CREDENTIAL = (1ULL << 21); // This tag is dlp credential service.
constexpr uint64_t HITRACE_TAG_ACCESS_CONTROL = (1ULL << 22); // This tag is access control tag.
constexpr uint64_t HITRACE_TAG_NET = (1ULL << 23); // Net tag.
constexpr uint64_t HITRACE_TAG_NWEB = (1ULL << 24); // NWeb tag.
constexpr uint64_t HITRACE_TAG_HUKS = (1ULL << 25); // This tag is huks.
constexpr uint64_t HITRACE_TAG_USERIAM = (1ULL << 26); // This tag is useriam.
constexpr uint64_t HITRACE_TAG_DISTRIBUTED_AUDIO = (1ULL << 27); // Distributed audio tag.
constexpr uint64_t HITRACE_TAG_DLSM = (1ULL << 28); // device security level tag.
constexpr uint64_t HITRACE_TAG_FILEMANAGEMENT = (1ULL << 29); // filemanagement tag.
constexpr uint64_t HITRACE_TAG_OHOS = (1ULL << 30); // OHOS generic tag.
constexpr uint64_t HITRACE_TAG_ABILITY_MANAGER = (1ULL << 31); // Ability Manager tag.
constexpr uint64_t HITRACE_TAG_ZCAMERA = (1ULL << 32); // Camera module tag.
constexpr uint64_t HITRACE_TAG_ZMEDIA = (1ULL << 33); // Media module tag.
constexpr uint64_t HITRACE_TAG_ZIMAGE = (1ULL << 34); // Image module tag.
constexpr uint64_t HITRACE_TAG_ZAUDIO = (1ULL << 35); // Audio module tag.
constexpr uint64_t HITRACE_TAG_DISTRIBUTEDDATA = (1ULL << 36); // Distributeddata manager module tag.
constexpr uint64_t HITRACE_TAG_MDFS = (1ULL << 37); // Mobile distributed file system tag.
constexpr uint64_t HITRACE_TAG_GRAPHIC_AGP = (1ULL << 38); // Graphic module tag.
constexpr uint64_t HITRACE_TAG_ACE = (1ULL << 39); // ACE development framework tag.
constexpr uint64_t HITRACE_TAG_NOTIFICATION = (1ULL << 40); // Notification module tag.
constexpr uint64_t HITRACE_TAG_MISC = (1ULL << 41); // Notification module tag.
constexpr uint64_t HITRACE_TAG_MULTIMODALINPUT = (1ULL << 42); // Multi modal module tag.
constexpr uint64_t HITRACE_TAG_SENSORS = (1ULL << 43); // Sensors mudule tag.
constexpr uint64_t HITRACE_TAG_MSDP = (1ULL << 44); // Multimodal Sensor Data Platform module tag.
constexpr uint64_t HITRACE_TAG_DSOFTBUS = (1ULL << 45); // Distributed Softbus tag.
constexpr uint64_t HITRACE_TAG_RPC = (1ULL << 46); // RPC and IPC tag.
constexpr uint64_t HITRACE_TAG_ARK = (1ULL << 47); // ARK tag.
constexpr uint64_t HITRACE_TAG_WINDOW_MANAGER = (1ULL << 48); // window manager tag.
constexpr uint64_t HITRACE_TAG_ACCOUNT_MANAGER = (1ULL << 49); // account manager tag.
constexpr uint64_t HITRACE_TAG_DISTRIBUTED_SCREEN = (1ULL << 50); // Distributed screen tag.
constexpr uint64_t HITRACE_TAG_DISTRIBUTED_CAMERA = (1ULL << 51); // Distributed camera tag.
constexpr uint64_t HITRACE_TAG_DISTRIBUTED_HARDWARE_FWK = (1ULL << 52); // Distributed hardware fwk tag.
constexpr uint64_t HITRACE_TAG_GLOBAL_RESMGR = (1ULL << 53); // Global resource manager tag.
constexpr uint64_t HITRACE_TAG_DEVICE_MANAGER = (1ULL << 54); // Distributed hardware devicemanager tag.
constexpr uint64_t HITRACE_TAG_SAMGR = (1ULL << 55); // SA tag.
constexpr uint64_t HITRACE_TAG_POWER = (1ULL << 56); // power manager tag.
constexpr uint64_t HITRACE_TAG_DISTRIBUTED_SCHEDULE = (1ULL << 57); // Distributed schedule tag.
constexpr uint64_t HITRACE_TAG_DEVICE_PROFILE = (1ULL << 58); // device profile tag.
constexpr uint64_t HITRACE_TAG_DISTRIBUTED_INPUT = (1ULL << 59); // Distributed input tag.
constexpr uint64_t HITRACE_TAG_BLUETOOTH = (1ULL << 60); // bluetooth tag.
constexpr uint64_t HITRACE_TAG_ACCESSIBILITY_MANAGER = (1ULL << 61); // accessibility manager tag.
constexpr uint64_t HITRACE_TAG_APP = (1ULL << 62); // App tag.
constexpr uint64_t HITRACE_TAG_LAST = HITRACE_TAG_APP;
constexpr uint64_t HITRACE_TAG_NOT_READY = (1ULL << 63); // Reserved for initialization.
constexpr uint64_t HITRACE_TAG_VALID_MASK = ((HITRACE_TAG_LAST - 1) | HITRACE_TAG_LAST);
```
## Implementation Principle
HiTraceMeter provides the hitrace CLI tool for capturing trace data in user mode and kernel mode, and provides C++ (innerkits) and JS (kits) APIs for event logging in user mode. Through extending kernel's ftrace functionality, HiTraceMeter can use the trace_marker node of ftrace to write the data, which is written into the user space by event logging APIs, to the kernel buffer. The following figure shows the basic HiTraceMeter architecture.
![HiTraceMeter architecture](figure/HiTraceMeter.png)
## Constraints
- The implementation of HiTraceMeter functions and APIs depends on the ftrace functionality, a framework provided by the kernel. It enables developers to add more trace functions via plug-ins. Therefore, make sure that ftrace is enabled before you use HiTraceMeter.
For most Linux kernels, ftrace is enabled by default. For details, see the ftrace documentation you may obtain.
- HiTraceMeter is available only for the mini system and standard system.
# HiTraceMeter Development
HiTraceMeter development focuses on two parts: JS/C++ event logging APIs and the hitrace CLI tool.
## When to Use
You may encounter unexpected issues like app freezing during app development or need to view the code's call chain during code debugging. With the APIs provided by HiTraceMeter, you'll be able to trace the application delay and call chain to identify performance problems.
## Available APIs
Only C++ APIs are now open for system developers. If you're developing a JS app, skip this section. The following table describes the APIs applicable to the standard system. You can find the APIs in [hitrace_meter.h](https://gitee.com/openharmony/hiviewdfx_hitrace/blob/master/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h).
**Table 1** Sync APIs
| API | Function |Parameter Description |
| :----------------------------------------------------------- | ------------- |------------- |
| void StartTrace(uint64_t label, const std::string& value, float limit = -1); | Starts a synchronous trace.|**label**: trace category.<br>**value**: trace data that indicates the specific status, such as the memory size and queue length.|
| void FinishTrace(uint64_t label); | Stops a synchronous trace.|**label**: trace category.|
**StartTrace** and **FinishTrace** must be used in pairs, and **FinishTrace** matches the latest **StartTrace**. The two APIs can be used in nested mode. The stack data structure is used for matching during trace data parsing. The **limit** parameter is used for flow control, and you are advised to use the default value.
**Table 2** Async APIs
| API | Function |Parameter Description |
| ------------------------------------------------------------ | ------------- |------------- |
| void StartAsyncTrace(uint64_t label, const std::string& value, int32_t taskId, float limit = -1); | Starts an asynchronous trace.| **label**: trace category.<br>**value**: trace data that indicates the specific status, such as the memory size and queue length.<br>**taskId**: ID used to indicate the association of APIs in an asynchronous trace.|
| void FinishAsyncTrace(uint64_t label, const std::string& value, int32_t taskId); | Stops an asynchronous trace.| **label**: trace category.<br>**value**: trace data that indicates the specific status, such as the memory size and queue length.<br>**taskId**: ID used to indicate the association of APIs in an asynchronous trace.|
The trace data of **StartAsyncTrace** and **FinishAsyncTrace** is matched based on **value** and **taskId**, and therefore, the two APIs can be used without a strict sequence. In C++ applications, asynchronous traces are seldom used.
**Table 3** Counter APIs
| API | Function |Parameter Description |
| ------------------------------------------------------------ | --------- |--------- |
| void CountTrace(uint64_t label, const std::string& name, int64_t); | Performs a count trace.|**label**: trace category.<br>**name**: trace name displayed in the IDE.|
## How to Develop
1. Add the build dependencies to the build configuration file **base\hiviewdfx\hitrace\cmd\BUILD.gn**.
```
external_deps = [ "hitrace_native:hitrace_meter"]
```
2. Add the header file dependencies.
```cpp
#include "hitrace_meter.h"// Header file for defining APIs
```
3. When calling an API, pass the trace value as an input parameter. After the hitrace command is executed in the shell, the trace data is automatically captured. The captured data includes the function call process and the memory and time consumed during this process. You can use the data to analyze the call process to identify performance problems.
```cpp
CountTrace(label, "count number", 2000); // Integer trace
StartTrace(label, "func1Trace", -1); // Trace start point of func1Start
FinishTrace(label); // Trace end point of func1Trace
StartAsyncTrace(label, "asyncTrace1", 1234); // Start point of asyncTrace1
FinishAsyncTrace(label, "asyncTrace2", 3456); // End point of asyncTrace2
```
4. On completion of HiTraceMeter building and deployment, start a trace. After you run the application in the shell on the device, trace data will be captured automatically.
```
hdc_std shell hitrace -t 10 ohos > .\myapp_demo.ftrace
```
You can open the captured data by clicking **Open trace file** in the smartperf tool or dragging the data to the graphics area. For details, see [smartperf](https://toscode.gitee.com/openharmony-sig/smartperf).
## Development Example
You can access a full list of trace tags supported by HiTraceMeter in **hitrace_meter.h**. The following uses the **OHOS** tag as an example to illustrate how to obtain the trace data of the **func1** and **func2** functions.
```cpp
#include "hitrace_meter.h" // Include hitrace_meter.h
using namespace std;
int main()
{
uint64_t label = BYTRACE_TAG_OHOS;
sleep(1);
CountTrace(label, "count number", 2000); // Integer trace
StartTrace(label, "func1Trace", -1); // Trace start point of func1Start
sleep(1);
StartTrace(label, "func2Trace", -1); // Trace start point of func2Start
sleep(2);
FinishTrace (label); // Trace end point of func2Trace
sleep(1);
FinishTrace(label); // Trace end point of func1Trace
return 0;
}
```
## Verification
The following is a demo debugging process, where the **StartTrace** and **FinishTrace** APIs are used in synchronization mode.
1. Write the test code file [hitrace_example.cpp](https://gitee.com/openharmony/hiviewdfx_hitrace/blob/master/cmd/example/hitrace_example.cpp) by adding the **StartTrace** and **FinishTrace** APIs to the code.
```cpp
int main()
{
thread t1(ThreadFunc1);
t1.join();
StartTrace(LABEL, "testStart");
sleep(SLEEP_ONE_SECOND);
StartTrace(LABEL, "funcAStart", SLEEP_ONE_SECOND); // Trace start point
FuncA();
FinishTrace(LABEL);
sleep(SLEEP_TWO_SECOND);
thread t2(ThreadFunc2);
t2.join();
StartTrace(LABEL, "funcBStart", SLEEP_TWO_SECOND);
FuncB();
FinishTrace(LABEL);// Trace end point
sleep(SLEEP_TWO_SECOND);
sleep(SLEEP_ONE_SECOND);
FinishTrace(LABEL);
FuncC();
return 0;
}
```
2. Modify the **base\hiviewdfx\hitrace\cmd\BUILD.gn** file, and start building.
```
ohos_executable("hitrace_example") {
sources = [ "example/hitrace_example.cpp" ]
external_deps = [ "hitrace_native:hitrace_meter" ]
subsystem_name = "hiviewdfx"
part_name = "hitrace_native"
}
group("hitrace_target") {
deps = [
":hitrace",
":hitrace_example",
]
}
```
3. Place the **hitrace_example** executable file in the **/system/bin** directory of the device, and run the following commands in sequence in the shell:
```shell
hitrace --trace_begin ohos
hitrace_exampe
hitrace --trace_dump
```
If the expected trace value is present in the trace data, the capture of trace data is successful. For example:
```
<...>-1651 (-------) [002] .... 327.194136: tracing_mark_write: S|1650|H:testAsync 111
<...>-1650 (-------) [001] .... 332.197640: tracing_mark_write: B|1650|H:testStart
<...>-1650 (-------) [001] .... 333.198018: tracing_mark_write: B|1650|H:funcAStart
<...>-1650 (-------) [001] .... 334.198507: tracing_mark_write: E|1650|
<...>-1654 (-------) [003] .... 341.201673: tracing_mark_write: F|1650|H:testAsync 111
<...>-1650 (-------) [001] .... 341.202168: tracing_mark_write: B|1650|H:funcBStart
<...>-1650 (-------) [001] .... 343.202557: tracing_mark_write: E|1650|
<...>-1650 (-------) [001] .... 346.203178: tracing_mark_write: E|1650|
<...>-1650 (-------) [001] .... 346.203457: tracing_mark_write: C|1650|H:count number 1
<...>-1650 (-------) [001] .... 347.203818: tracing_mark_write: C|1650|H:count number 2
<...>-1650 (-------) [001] .... 348.204207: tracing_mark_write: C|1650|H:count number 3
<...>-1650 (-------) [001] .... 349.204473: tracing_mark_write: C|1650|H:count number 4
<...>-1650 (-------) [001] .... 350.204851: tracing_mark_write: C|1650|H:count number 5
<...>-1655 (-------) [001] .... 365.944658: tracing_mark_write: trace_event_clock_sync: realtime_ts=1502021460925
<...>-1655 (-------) [001] .... 365.944686: tracing_mark_write: trace_event_clock_sync: parent_ts=365.944641
```
# Using the hitrace CLI Tool
The hitrace CLI tool is an executable binary program. On an OpenHarmony-powered device, you can run the following commands in the shell to capture kernel's running data.
**Table 4** Command list
| Option | Description |
| ------------------------------ | ------------------------------------------------------------ |
| -h, --help | Views the help Information. |
| -b *n*, --buffer_size *n* | Sets the buffer size for trace data in KB. The default value is **2048**. |
| -t *n*, --time *n* | Sets the trace uptime in seconds, which depends on the time required for analysis.|
| --trace_clock clock | Sets the type of the clock for adding a timestamp to a trace. The value can be **boot** (default), **global**, **mono**, **uptime**, or **perf**.|
| --trace_begin | Starts capturing trace data. |
| --trace_dump | Dumps trace data to the specified position. The default position is the console. |
| --trace_finish | Stops capturing trace data and dumps trace data to the specified position. The default position is the console. |
| -l, --list_categories | Lists the trace categories supported by the device. |
| --overwrite | Sets the action to take when the buffer is full. If this option is used, the latest trace data is discarded. If this option is not used, the earliest trace data is discarded (default). |
| -o *filename*, --output *filename*| Outputs trace data to the specified file. |
| -z | Compresses the trace data. |
Examples:
- Query supported labels.
```
hitrace -l
```
Or,
```
hitrace --list_categories
```
- Trace ability information for 10 seconds and store the trace data in a buffer of 4 MB.
```
hitrace -b 4096 -t 10 --overwrite ability > /data/log/mytrace.ftrace
```
- Set the clock type to **mono**.
```
hitrace --trace_clock mono -b 4096 -t 10 --overwrite ability > /data/log/mytrace.ftrace
```
- Compress the trace data.
```
hitrace -z -b 4096 -t 10 --overwrite ability > /data/log/mytrace.ftrace
```
# FAQs
### Incomplete or Empty Data Captured by hitrace
#### Symptom
The data captured by running the hitrace command is incomplete or no data is captured.
#### Solution
Check the value of the **-t** and **-b** parameters. If the value is too small, data loss will occur. You are advised to set **-t** to **60** and **-b** to **204800** to increase the trace capture time and buffer, respectively.
# References
For details about HiTraceMeter, see [hiviewdfx_hitrace: A Lightweight Distributed Tracing](https://gitee.com/openharmony/hiviewdfx_hitrace).
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册