提交 67b7b12e 编写于 作者: D duangavin123

update 导入OpenHarmony工程

Signed-off-by: Nduangavin123 <duanxichao@huawei.com>
上级 da68c8bc
......@@ -36,7 +36,7 @@ OpenHarmony provides the following two types of Docker environments for you to q
</thead>
<tbody><tr id="row167901244115315"><td class="cellrowborder" valign="top" width="35.5064493550645%" headers="mcps1.2.4.1.1 "><p id="p87901744185316"><a name="p87901744185316"></a><a name="p87901744185316"></a>swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker</p>
</td>
<td class="cellrowborder" valign="top" width="10.258974102589741%" headers="mcps1.2.4.1.2 "><p id="p15790184410536"><a name="p15790184410536"></a><a name="p15790184410536"></a>0.0.3</p>
<td class="cellrowborder" valign="top" width="10.258974102589741%" headers="mcps1.2.4.1.2 "><p id="p15790184410536"><a name="p15790184410536"></a><a name="p15790184410536"></a>0.0.5</p>
</td>
<td class="cellrowborder" valign="top" width="54.23457654234577%" headers="mcps1.2.4.1.3 "><p id="p15790124416531"><a name="p15790124416531"></a><a name="p15790124416531"></a>The <span id="text929334781813"><a name="text929334781813"></a><a name="text929334781813"></a>OpenHarmony</span> build environment has been pre-installed. This repository applies to <span id="text167042559153"><a name="text167042559153"></a><a name="text167042559153"></a>Mini-System Devices (reference memory ≥ 128 KB)</span> and <span id="text358943111611"><a name="text358943111611"></a><a name="text358943111611"></a>Small-System Devices (reference memory ≥ 1 MB)</span>.</p>
</td>
......@@ -78,7 +78,7 @@ Start building. Docker can be automatically installed only on Ubuntu. If you are
- **Automatically Installing Docker \(Ubuntu\)**
Running the following command will automatically install the Docker, pull the image, and start the pulling and building of the corresponding solution in the container.
Running the following command will automatically install Docker, pull the Docker image, and start the pulling and building of the corresponding solution in the container.
Method 1:
......@@ -123,8 +123,7 @@ Start building. Docker can be automatically installed only on Ubuntu. If you are
```
# Pull the image.
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3
# Build the distribution on Linux.
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3# Compile the Docker image in the Linux environment.
hpm run distWithDocker solution={product}
# When using Windows, make sure to configure the Git Bash.
hpm config set shellPath "Git Bash path"
......@@ -134,22 +133,22 @@ Start building. Docker can be automatically installed only on Ubuntu. If you are
## Standalone Docker Environment<a name="section2858536103611"></a>
The Docker image of OpenHarmony is hosted on [HUAWEI Cloud SWR](https://auth.huaweicloud.com/authui/login.html?service=https%3A%2F%2Fconsole.huaweicloud.com%2Fswr%2F%3Fregion%3Dcn-south-1%26cloud_route_state%3D%2Fapp%2Fwarehouse%2FwarehouseMangeDetail%2Fgoldensir%2Fopenharmony-docker%2Fopenharmony-docker%3Ftype%3DownImage&locale=en-us#/login). Using the Docker image will help simplify environment configurations needed for the building. After configuring the development environments, perform the procedures below to access the Docker environment. Both Ubuntu and Windows are supported. The following procedures use Ubuntu as an example.
The Docker image of OpenHarmony is hosted on [HUAWEI CLOUD SWR](https://console.huaweicloud.com/swr/?region=cn-south-1&locale=en-us#/app/warehouse/warehouseMangeDetail/goldensir/openharmony-docker/openharmony-docker?type=ownImage). Using the Docker image will help simplify environment configurations needed for the building. After configuring the development environments, perform the procedures below to access the Docker environment. Both Ubuntu and Windows are supported. The following procedures use Ubuntu as an example.
### Setting Up the Docker Environment for Mini-System Devices \(reference memory ≥ 128 KB\) and Small-System Devices \(reference memory ≥ 1 MB\)<a name="section319412277287"></a>
**Method 1: Obtaining the Docker image from HuaweiCloud SWR**
**Method 1: Obtaining the Docker image from HUAWEI CLOUD SWR**
1. Obtain the Docker image.
```
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5
```
2. Go to the root directory of OpenHarmony code and run the following command to access the Docker build environment:
```
docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3
docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5
```
......@@ -171,7 +170,7 @@ The Docker image of OpenHarmony is hosted on [HUAWEI Cloud SWR](https://auth.hu
3. Go to the root directory of OpenHarmony code and run the following command to access the Docker build environment:
```
docker run -it -v $(pwd):/home/openharmony openharmony-docker:0.0.3
docker run -it -v $(pwd):/home/openharmony openharmony-docker:0.0.5
```
......@@ -211,7 +210,7 @@ hb set
### Setting Up the Docker Environment for Standard-System Devices \(reference memory ≥ 128 MB\)<a name="section13585262391"></a>
**Method 1: Obtaining the Docker image from HuaweiCloud SWR**
**Method 1: Obtaining the Docker image from HUAWEI CLOUD SWR**
1. Obtain the Docker image.
......@@ -274,6 +273,10 @@ hb set
HUAWEI DevEco Device Tool is a one-stop integrated development environment \(IDE\) provided to develop applications for OpenHarmony-based smart devices. It allows on-demand customization of OpenHarmony components, code editing, compilation, burning, and debugging, and supports C and C++ languages. This tool is installed in Visual Studio Code as a plug-in. For details, see [Tool Acquisition](https://device.harmonyos.com/en/ide) and [HUAWEI DevEco Device Tool User Guide](https://device.harmonyos.com/en/docs/ide/user-guides/service_introduction-0000001050166905).
The roadmap of Huawei DevEco Device Tool for supporting OpenHarmony device development is shown in the figure below.
![](figures/3.png)
## Acquiring the Application Development Tool \(HUAWEI DevEco Studio\)<a name="section0904101019258"></a>
HUAWEI DevEco Studio \(DevEco Studio for short\) is a one-stop IDE oriented to Huawei devices in all scenarios. It provides E2E OpenHarmony application development services, ranging from project template creation to development, compilation, debugging, and release. With DevEco Studio, you will be able to efficiently develop OpenHarmony applications with distributed capabilities while speeding up innovation. For details, see [Tool Acquisition](https://developer.harmonyos.com/en/develop/deveco-studio) and [HUAWEI DevEco Studio User Guide](https://developer.harmonyos.com/en/docs/documentation/doc-guides/tools_overview-0000001053582387).
......
# OpenHarmony 1.1.1 LTS \(2021-06-22\) <a name="EN-US_TOPIC_0000001115559984"></a>
- [Version Description](#section1846294912228)
- [Source Code Acquisition](#section84808293211)
- [Acquiring Source Code from Image Sites](#section8394142222113)
- [Acquiring Source Code Using the repo Tool](#section7180193542317)
- [What's New](#section175225345334)
## Version Description<a name="section1846294912228"></a>
This is an updated long-term support \(LTS\) version of OpenHarmony. It supports more functions and fixes some bugs in OpenHarmony 1.1.0.
## Source Code Acquisition<a name="section84808293211"></a>
### Acquiring Source Code from Image Sites<a name="section8394142222113"></a>
**Table 1** Sites for acquiring source code
<a name="table14394152217216"></a>
<table><thead align="left"><tr id="row15394132214217"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p15394122214219"><a name="p15394122214219"></a><a name="p15394122214219"></a>Source Code</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p10394112292119"><a name="p10394112292119"></a><a name="p10394112292119"></a>Version</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.3"><p id="p039562213211"><a name="p039562213211"></a><a name="p039562213211"></a>Site</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.4"><p id="p1039572272110"><a name="p1039572272110"></a><a name="p1039572272110"></a>SHA-256 Verification Code</p>
</th>
</tr>
</thead>
<tbody><tr id="row9395722182111"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p039514225215"><a name="p039514225215"></a><a name="p039514225215"></a>Full code base</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p839514220217"><a name="p839514220217"></a><a name="p839514220217"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p15931114016546"><a name="p15931114016546"></a><a name="p15931114016546"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/code-v1.1.1-LTS.tar.gz" target="_blank" rel="noopener noreferrer">Site</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p3770144281415"><a name="p3770144281415"></a><a name="p3770144281415"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/code-v1.1.1-LTS.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td>
</tr>
<tr id="row1739512225217"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1839592272117"><a name="p1839592272117"></a><a name="p1839592272117"></a>Hi3861 solution (binary)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p7395722112113"><a name="p7395722112113"></a><a name="p7395722112113"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p29291940175415"><a name="p29291940175415"></a><a name="p29291940175415"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/wifiiot-1.1.0.tar.gz" target="_blank" rel="noopener noreferrer">Site</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p134864584147"><a name="p134864584147"></a><a name="p134864584147"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/wifiiot-1.1.0.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td>
</tr>
<tr id="row16395122262110"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p12395172242118"><a name="p12395172242118"></a><a name="p12395172242118"></a>Hi3518 solution (binary)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p12395182210215"><a name="p12395182210215"></a><a name="p12395182210215"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p125681045181518"><a name="p125681045181518"></a><a name="p125681045181518"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/ipcamera_hi3518ev300-1.1.1.tar.gz" target="_blank" rel="noopener noreferrer">Site</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p4607175915149"><a name="p4607175915149"></a><a name="p4607175915149"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/ipcamera_hi3518ev300-1.1.1.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td>
</tr>
<tr id="row1839592272117"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p8395322182113"><a name="p8395322182113"></a><a name="p8395322182113"></a>Hi3516 solution (binary)</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p20395152262114"><a name="p20395152262114"></a><a name="p20395152262114"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p10455184661518"><a name="p10455184661518"></a><a name="p10455184661518"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/ipcamera_hi3516dv300-1.1.1.tar.gz" target="_blank" rel="noopener noreferrer">Site</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p84951102150"><a name="p84951102150"></a><a name="p84951102150"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/ipcamera_hi3516dv300-1.1.1.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td>
</tr>
<tr id="row3396822162120"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p18506191313914"><a name="p18506191313914"></a><a name="p18506191313914"></a>Release Notes</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p10396102282110"><a name="p10396102282110"></a><a name="p10396102282110"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p88931840195416"><a name="p88931840195416"></a><a name="p88931840195416"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/OpenHarmony_Release_Notes 1.1.1 LTS.zip" target="_blank" rel="noopener noreferrer">Site</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p039662242117"><a name="p039662242117"></a><a name="p039662242117"></a>-</p>
</td>
</tr>
</tbody>
</table>
### Acquiring Source Code Using the repo Tool<a name="section7180193542317"></a>
Run the following commands to download the source code:
repo init -u [https://gitee.com/openharmony/manifest.git](https://gitee.com/openharmony/manifest.git) -b refs/tags/OpenHarmony-v1.1.1-LTS --no-repo-verify
## What's New<a name="section175225345334"></a>
This version inherits all features of OpenHarmony 1.1.0, and fixes bugs and optimizes performance for different modules based on OpenHarmony 1.1.0. The following table lists the updates.
**Table 2** Version updates
<a name="table143385853320"></a>
<table><thead align="left"><tr id="row53375863312"><th class="cellrowborder" valign="top" width="25.77%" id="mcps1.2.3.1.1"><p id="p20331858193317"><a name="p20331858193317"></a><a name="p20331858193317"></a>Type</p>
</th>
<th class="cellrowborder" valign="top" width="74.22999999999999%" id="mcps1.2.3.1.2"><p id="p1133115820331"><a name="p1133115820331"></a><a name="p1133115820331"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row333115812331"><td class="cellrowborder" valign="top" width="25.77%" headers="mcps1.2.3.1.1 "><p id="p2142111345714"><a name="p2142111345714"></a><a name="p2142111345714"></a>Communications</p>
</td>
<td class="cellrowborder" valign="top" width="74.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul9264132010"></a><a name="ul9264132010"></a><ul id="ul9264132010"><li>Updated data classes of some STA related functions, and added innerkits APIs of some AP related functions</li><li>Added innerkits APIs for Bluetooth-related functions, including GATT related operations of BLE devices, BLE broadcast, and scanning.</li></ul>
</td>
</tr>
<tr id="row15331058133314"><td class="cellrowborder" valign="top" width="25.77%" headers="mcps1.2.3.1.1 "><p id="p056093211916"><a name="p056093211916"></a><a name="p056093211916"></a>Security</p>
</td>
<td class="cellrowborder" valign="top" width="74.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul166113311811"></a><a name="ul166113311811"></a><ul id="ul166113311811"><li>Removed device authentication so callers can use bound capabilities alone.</li><li>Allowed device authentication removed from Huawei Universal Keystore Service (HUKS).</li></ul>
</td>
</tr>
<tr id="row334175803317"><td class="cellrowborder" valign="top" width="25.77%" headers="mcps1.2.3.1.1 "><p id="p382391145710"><a name="p382391145710"></a><a name="p382391145710"></a>Kernel</p>
</td>
<td class="cellrowborder" valign="top" width="74.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul334485413318"></a><a name="ul334485413318"></a><ul id="ul334485413318"><li>Fixed the bug of unavailable kernel stack backtracking of the system image built using Clang.</li><li>Fixed the bug of improper comparison between signed numbers and unsigned numbers during scheduling.</li><li>Fixed the bug of memory overwriting because <strong id="b13489525183218"><a name="b13489525183218"></a><a name="b13489525183218"></a>setitimer</strong> does not hold the scheduler lock when periodically sending signals to the process.</li><li>Added adaptation to the kernel's POSIX APIs for lwIP.</li><li>Fixed the bug of unexpected signal execution sequence after <strong id="b35501817191415"><a name="b35501817191415"></a><a name="b35501817191415"></a>sigsuspend</strong> in <strong id="b1255791961411"><a name="b1255791961411"></a><a name="b1255791961411"></a>sigaction</strong> is called; fixed the bug so that the signal mask field passed by the developer is now masked during signal registration.</li></ul>
</td>
</tr>
<tr id="row834358143319"><td class="cellrowborder" valign="top" width="25.77%" headers="mcps1.2.3.1.1 "><p id="p1818191195713"><a name="p1818191195713"></a><a name="p1818191195713"></a>Driver</p>
</td>
<td class="cellrowborder" valign="top" width="74.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul4367144411512"></a><a name="ul4367144411512"></a><ul id="ul4367144411512"><li>Corrected the compilation error on <strong id="b8364125020151"><a name="b8364125020151"></a><a name="b8364125020151"></a>liteos_m</strong>.</li><li>Fixed MMC crashes.</li></ul>
</td>
</tr>
<tr id="row119944512385"><td class="cellrowborder" valign="top" width="25.77%" headers="mcps1.2.3.1.1 "><p id="p919862210573"><a name="p919862210573"></a><a name="p919862210573"></a>AI</p>
</td>
<td class="cellrowborder" valign="top" width="74.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul12374158862"></a><a name="ul12374158862"></a><ul id="ul12374158862"><li>Added support for shared memory.</li><li>Added adaptation to the Linux kernel.</li><li>Disabled asynchronous call for the synchronous algorithm.</li><li>Added gitignore and CMakeLists.</li></ul>
</td>
</tr>
<tr id="row18711154213388"><td class="cellrowborder" valign="top" width="25.77%" headers="mcps1.2.3.1.1 "><p id="p111921822185713"><a name="p111921822185713"></a><a name="p111921822185713"></a>Graphics</p>
</td>
<td class="cellrowborder" valign="top" width="74.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul94024441879"></a><a name="ul94024441879"></a><ul id="ul94024441879"><li>Fixed the bug that occurs when the endpoint style is enabled for circle progress.</li><li>Resolved issues related to the sensitivity and direction of crown rotation.</li><li>Added the feature of automatic alignment with the animation time for <strong id="b28311553182611"><a name="b28311553182611"></a><a name="b28311553182611"></a>UIList</strong>.</li><li>Provided correct width for <strong id="b7207142820308"><a name="b7207142820308"></a><a name="b7207142820308"></a>GetTextWidth</strong> in <strong id="b491024617492"><a name="b491024617492"></a><a name="b491024617492"></a>UILabel</strong> when <strong id="b167271343114912"><a name="b167271343114912"></a><a name="b167271343114912"></a>LineBreakMode</strong> is set to <strong id="b199351540154910"><a name="b199351540154910"></a><a name="b199351540154910"></a>LINE_BREAK_ELLIPSIS</strong>.</li><li>Added new style attributes to the <strong id="b1873219205012"><a name="b1873219205012"></a><a name="b1873219205012"></a>Slider</strong> component.</li><li>Added the API for setting loops to the <strong id="b247622375012"><a name="b247622375012"></a><a name="b247622375012"></a>UITimePicker</strong> component.</li><li>Fixed the bug of abnormal Neon rotation and scaling display that results from optimization of fixed-point numbers.</li><li>Rectified the improper newline issue that occurs when a string contains multiple newlines.</li><li>Fixed the bug of the blurred screen of watch pointers.</li></ul>
</td>
</tr>
<tr id="row933514718399"><td class="cellrowborder" valign="top" width="25.77%" headers="mcps1.2.3.1.1 "><p id="p61891022105712"><a name="p61891022105712"></a><a name="p61891022105712"></a>Globalization</p>
</td>
<td class="cellrowborder" valign="top" width="74.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul134825147387"></a><a name="ul134825147387"></a><ul id="ul134825147387"><li>Added the <strong id="b187011621105114"><a name="b187011621105114"></a><a name="b187011621105114"></a>Ed</strong> and <strong id="b1184852319516"><a name="b1184852319516"></a><a name="b1184852319516"></a>MEd</strong> templates for data and time formatting.</li></ul>
</td>
</tr>
<tr id="row98001376403"><td class="cellrowborder" valign="top" width="25.77%" headers="mcps1.2.3.1.1 "><p id="p195826175717"><a name="p195826175717"></a><a name="p195826175717"></a>ACE framework</p>
</td>
<td class="cellrowborder" valign="top" width="74.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul1246016241096"></a><a name="ul1246016241096"></a><ul id="ul1246016241096"><li>Fixed the bug of abnormal click events on the checkbox and radio buttons.</li><li>Fixed JavaScript application crashes when <strong id="b1694301120523"><a name="b1694301120523"></a><a name="b1694301120523"></a>list</strong> and <strong id="b1650051311529"><a name="b1650051311529"></a><a name="b1650051311529"></a>if</strong> are used.</li><li>Normalized the styles of the <strong id="b1856819441529"><a name="b1856819441529"></a><a name="b1856819441529"></a>&lt;slider&gt;</strong> component.</li><li>Added swiping loops for the <strong id="b116556577525"><a name="b116556577525"></a><a name="b116556577525"></a>&lt;picker-view&gt;</strong> component.</li><li>Fixed the bug of in-the-middle display of child components when <strong id="b168956443532"><a name="b168956443532"></a><a name="b168956443532"></a>align-item</strong> is set to <strong id="b1872216473538"><a name="b1872216473538"></a><a name="b1872216473538"></a>stretch</strong>.</li></ul>
</td>
</tr>
</tbody>
</table>
......@@ -7,7 +7,7 @@
- [前提条件](#section102871547153314)
- [操作步骤](#section429012478331)
- [获取方式2:从HPM(包管理器)组件式获取](#section463013147412)
- [获取方式2:从HPM获取](#section463013147412)
- [适用场景](#section26661067443)
- [前提条件](#section17544943123315)
- [操作步骤](#section954619433333)
......@@ -50,8 +50,8 @@ OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及
### 前提条件<a name="section102871547153314"></a>
1. 注册码云gitee账号。
2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4181)
3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading)并配置用户信息。
2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)
3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。
```
git config --global user.name "yourname"
......@@ -70,73 +70,46 @@ OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及
### 操作步骤<a name="section429012478331"></a>
**获取轻量系统/小型系统源码**
**获取轻量/小型/标准系统(2.0 Canary)源码**
>![](public_sys-resources/icon-note.gif) **说明:**
>主干代码为开发分支,开发者可通过主干代码获取最新特性。release分支代码相对比较稳定,开发者可基于release分支代码进行商用功能开发。
- **OpenHarmony主干代码获取**
方式一(推荐):通过repo下载
方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。
```
repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
```
方式二:通过git clone单个代码仓库
进入[代码仓库主页](https://gitee.com/openharmony),选择需要克隆的代码仓库,执行命令,如:
```
git clone https://gitee.com/openharmony/manifest.git -b master
```
- **OpenHarmony release 分支代码获取**
通过repo下载
方式二:通过repo + https 下载。
```
repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony_1.0.1_release --no-repo-verify
repo sync -c
repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
```
- **OpenHarmony** 其他版本源码获取方式请参考版本[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md)
**获取标准系统源码(2.0 Canary)**
- **OpenHarmony release 分支最新代码获取**
1. 创建并切换到OpenHarmony工作目录。
>![](public_sys-resources/icon-note.gif) **说明:**
>当前通过release分支只能获取轻量和小型系统源码。
```
mkdir OpenHarmony
cd OpenHarmony
```
2. repo初始化。
```
repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
# 使用此命令初始化时,可能会因为网络慢的问题导致代码更新失败,可以尝试以下命令来初始化:
repo init -u https://gitee.com/openharmony/manifest.git -b ssh/master --no-repo-verify
```
3. 更新代码。
```
repo sync -c
```
4. 更新二进制。
通过repo下载。
```
repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony_1.0.1_release --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
```
- **OpenHarmony** 其他版本源码获取方式请参考版本[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md)
## 获取方式2:从HPM(包管理器)组件式获取<a name="section463013147412"></a>
## 获取方式2:从HPM获取<a name="section463013147412"></a>
### 适用场景<a name="section26661067443"></a>
......@@ -238,45 +211,45 @@ OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及
</tr>
<tr id="row17736152318398"><td class="cellrowborder" valign="top" width="25%"><p id="p1110983610395"><a name="p1110983610395"></a><a name="p1110983610395"></a>全量代码(轻量和小型系统)</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p151091536143915"><a name="p151091536143915"></a><a name="p151091536143915"></a>1.1.0</p>
<td class="cellrowborder" valign="top" width="25%"><p id="p151091536143915"><a name="p151091536143915"></a><a name="p151091536143915"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p17110133653913"><a name="p17110133653913"></a><a name="p17110133653913"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.0/code-1.1.0.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
<td class="cellrowborder" valign="top" width="25%"><p id="p17110133653913"><a name="p17110133653913"></a><a name="p17110133653913"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/code-v1.1.1-LTS.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p1911083643914"><a name="p1911083643914"></a><a name="p1911083643914"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.0/code-1.1.0.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256 校验码</a></p>
<td class="cellrowborder" valign="top" width="25%"><p id="p1911083643914"><a name="p1911083643914"></a><a name="p1911083643914"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/code-v1.1.1-LTS.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256 校验码</a></p>
</td>
</tr>
<tr id="row473612318396"><td class="cellrowborder" valign="top" width="25%"><p id="p511014369394"><a name="p511014369394"></a><a name="p511014369394"></a>Hi3861解决方案(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p0110036193911"><a name="p0110036193911"></a><a name="p0110036193911"></a>1.1.0</p>
<td class="cellrowborder" valign="top" width="25%"><p id="p0110036193911"><a name="p0110036193911"></a><a name="p0110036193911"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p101106361397"><a name="p101106361397"></a><a name="p101106361397"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.0/wifiiot-1.1.0.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
<td class="cellrowborder" valign="top" width="25%"><p id="p101106361397"><a name="p101106361397"></a><a name="p101106361397"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/wifiiot-1.1.0.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p7110183617391"><a name="p7110183617391"></a><a name="p7110183617391"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.0/code-1.1.0.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256 校验码</a></p>
<td class="cellrowborder" valign="top" width="25%"><p id="p7110183617391"><a name="p7110183617391"></a><a name="p7110183617391"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/wifiiot-1.1.0.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256 校验码</a></p>
</td>
</tr>
<tr id="row873614239395"><td class="cellrowborder" valign="top" width="25%"><p id="p11110113633913"><a name="p11110113633913"></a><a name="p11110113633913"></a>Hi3518解决方案(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p18110193613391"><a name="p18110193613391"></a><a name="p18110193613391"></a>1.1.0</p>
<td class="cellrowborder" valign="top" width="25%"><p id="p18110193613391"><a name="p18110193613391"></a><a name="p18110193613391"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p611013618398"><a name="p611013618398"></a><a name="p611013618398"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.0/ipcamera_hi3518ev300-1.1.0.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p411023616393"><a name="p411023616393"></a><a name="p411023616393"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.0/ipcamera_hi3518ev300-1.1.0.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256 校验码</a></p>
<td class="cellrowborder" valign="top" width="25%"><p id="p411023616393"><a name="p411023616393"></a><a name="p411023616393"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/ipcamera_hi3518ev300-1.1.1.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256 校验码</a></p>
</td>
</tr>
<tr id="row1273682343914"><td class="cellrowborder" valign="top" width="25%"><p id="p15110123693919"><a name="p15110123693919"></a><a name="p15110123693919"></a>Hi3516解决方案(二进制)</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p1211012362396"><a name="p1211012362396"></a><a name="p1211012362396"></a>1.1.0</p>
<td class="cellrowborder" valign="top" width="25%"><p id="p1211012362396"><a name="p1211012362396"></a><a name="p1211012362396"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p6110163613918"><a name="p6110163613918"></a><a name="p6110163613918"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.0/ipcamera_hi3516dv300-1.1.0.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
<td class="cellrowborder" valign="top" width="25%"><p id="p6110163613918"><a name="p6110163613918"></a><a name="p6110163613918"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/ipcamera_hi3516dv300-1.1.1.tar.gz" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p10110183620394"><a name="p10110183620394"></a><a name="p10110183620394"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.0/ipcamera_hi3516dv300-1.1.0.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256 校验码</a></p>
<td class="cellrowborder" valign="top" width="25%"><p id="p10110183620394"><a name="p10110183620394"></a><a name="p10110183620394"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/ipcamera_hi3516dv300-1.1.1.tar.gz.sha256" target="_blank" rel="noopener noreferrer">SHA256 校验码</a></p>
</td>
</tr>
<tr id="row167371123163914"><td class="cellrowborder" valign="top" width="25%"><p id="p10110143610393"><a name="p10110143610393"></a><a name="p10110143610393"></a>RELEASE-NOTES</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p141101436193911"><a name="p141101436193911"></a><a name="p141101436193911"></a>1.1.0</p>
<td class="cellrowborder" valign="top" width="25%"><p id="p141101436193911"><a name="p141101436193911"></a><a name="p141101436193911"></a>1.1.1</p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p10111636193919"><a name="p10111636193919"></a><a name="p10111636193919"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.0/OpenHarmony_Release_Notes_zh_cn.zip" target="_blank" rel="noopener noreferrer">站点</a></p>
<td class="cellrowborder" valign="top" width="25%"><p id="p10111636193919"><a name="p10111636193919"></a><a name="p10111636193919"></a><a href="https://repo.huaweicloud.com/harmonyos/os/1.1.1/OpenHarmony_Release_Notes 1.1.1 LTS.zip" target="_blank" rel="noopener noreferrer">站点</a></p>
</td>
<td class="cellrowborder" valign="top" width="25%"><p id="p20111163663918"><a name="p20111163663918"></a><a name="p20111163663918"></a>-</p>
</td>
......
......@@ -36,7 +36,7 @@ OpenHarmony为开发者提供了两种Docker环境,以帮助开发者快速完
</thead>
<tbody><tr id="row167901244115315"><td class="cellrowborder" valign="top" width="35.5064493550645%" headers="mcps1.2.4.1.1 "><p id="p87901744185316"><a name="p87901744185316"></a><a name="p87901744185316"></a>swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker</p>
</td>
<td class="cellrowborder" valign="top" width="10.258974102589741%" headers="mcps1.2.4.1.2 "><p id="p15790184410536"><a name="p15790184410536"></a><a name="p15790184410536"></a>0.0.4</p>
<td class="cellrowborder" valign="top" width="10.258974102589741%" headers="mcps1.2.4.1.2 "><p id="p15790184410536"><a name="p15790184410536"></a><a name="p15790184410536"></a>0.0.5</p>
</td>
<td class="cellrowborder" valign="top" width="54.23457654234577%" headers="mcps1.2.4.1.3 "><p id="p15790124416531"><a name="p15790124416531"></a><a name="p15790124416531"></a>已经预安装<span id="text6790444135318"><a name="text6790444135318"></a><a name="text6790444135318"></a>OpenHarmony</span>版本的编译环境,支持<span id="text167042559153"><a name="text167042559153"></a><a name="text167042559153"></a>轻量系统类设备(参考内存≥128KB)</span>和<span id="text358943111611"><a name="text358943111611"></a><a name="text358943111611"></a>小型系统类设备(参考内存≥1MB)</span>的版本构建。</p>
</td>
......@@ -123,7 +123,7 @@ docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件
```
# 拉取镜像
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.4# linux环境下的编译
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3# linux环境下的编译
hpm run distWithDocker solution={product}
# windows下的编译,需要配置gitbash
hpm config set shellPath "gitbash路径"
......@@ -142,13 +142,13 @@ OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud
1. 获取Docker镜像。
```
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.4
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5
```
2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。
```
docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.4
docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5
```
......@@ -170,7 +170,7 @@ OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud
3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。
```
docker run -it -v $(pwd):/home/openharmony openharmony-docker:0.0.4
docker run -it -v $(pwd):/home/openharmony openharmony-docker:0.0.5
```
......
# 真机运行<a name="ZH-CN_TOPIC_0000001115258034"></a>
应用签名打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),然后将OpenHarmony系统烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[标准系统Hi3516快速入门](../quick-start/开发步骤-12.md)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载应用。
应用签名打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),然后将OpenHarmony系统烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[标准系统Hi3516快速入门](../quick-start/标准系统入门.md)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载应用。
1. 从开发者工具代码仓路径中获取hdc客户端。
......
# C++支持<a name="ZH-CN_TOPIC_0000001079036442"></a>
- [基本概念](#section11374125415814)
- [运行机制](#section125251720195)
- [开发指导](#section166302407911)
- [接口说明](#section1881825119919)
- [开发流程](#section76371145108)
- [编程实例](#section994427141111)
## 基本概念<a name="section11374125415814"></a>
C++作为目前使用最广泛的编程语言之一,支持类、封装、重载等特性,是在C语言基础上开发的一种面向对象的编程语言。
### 运行机制<a name="section125251720195"></a>
C++代码的识别主要由编译器支持,系统主要对全局对象进行构造函数调用,进行初始化操作。
## 开发指导<a name="section166302407911"></a>
### 接口说明<a name="section1881825119919"></a>
**表 1** C++支持接口
<a name="table14277123518139"></a>
<table><thead align="left"><tr id="row152771935131315"><th class="cellrowborder" valign="top" width="23.792379237923793%" id="mcps1.2.4.1.1"><p id="p1127733591316"><a name="p1127733591316"></a><a name="p1127733591316"></a>功能分类</p>
</th>
<th class="cellrowborder" valign="top" width="33.02330233023302%" id="mcps1.2.4.1.2"><p id="p22771357138"><a name="p22771357138"></a><a name="p22771357138"></a>接口名</p>
</th>
<th class="cellrowborder" valign="top" width="43.18431843184319%" id="mcps1.2.4.1.3"><p id="p327714358130"><a name="p327714358130"></a><a name="p327714358130"></a>描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row119525513581"><td class="cellrowborder" valign="top" width="23.792379237923793%" headers="mcps1.2.4.1.1 "><p id="p2099535514346"><a name="p2099535514346"></a><a name="p2099535514346"></a>使用C++特性的前置条件</p>
</td>
<td class="cellrowborder" valign="top" width="33.02330233023302%" headers="mcps1.2.4.1.2 "><p id="p3155620345"><a name="p3155620345"></a><a name="p3155620345"></a>LOS_CppSystemInit</p>
</td>
<td class="cellrowborder" valign="top" width="43.18431843184319%" headers="mcps1.2.4.1.3 "><p id="p4616566343"><a name="p4616566343"></a><a name="p4616566343"></a>C++构造函数初始化</p>
</td>
</tr>
</tbody>
</table>
### 开发流程<a name="section76371145108"></a>
使用C++特性之前,需要调用函数LOS\_CppSystemInit,实现C++构造函数初始化,其中被初始化的构造函数存在init\_array这个段中,段区间通过变量\_\_init\_array\_start\_\_\_\_init\_array\_end\_\_传递。
**表 2** 参数说明
<a name="table71191652173718"></a>
<table><thead align="left"><tr id="row1512085253715"><th class="cellrowborder" valign="top" width="42.77%" id="mcps1.2.3.1.1"><p id="p16120175233720"><a name="p16120175233720"></a><a name="p16120175233720"></a>参数</p>
</th>
<th class="cellrowborder" valign="top" width="57.230000000000004%" id="mcps1.2.3.1.2"><p id="p61205526372"><a name="p61205526372"></a><a name="p61205526372"></a>参数说明</p>
</th>
</tr>
</thead>
<tbody><tr id="row11120135213714"><td class="cellrowborder" valign="top" width="42.77%" headers="mcps1.2.3.1.1 "><p id="p1053212673917"><a name="p1053212673917"></a><a name="p1053212673917"></a>__init_array_start__</p>
</td>
<td class="cellrowborder" valign="top" width="57.230000000000004%" headers="mcps1.2.3.1.2 "><p id="p2208154219392"><a name="p2208154219392"></a><a name="p2208154219392"></a>init_array段起始位置</p>
</td>
</tr>
<tr id="row1591908143918"><td class="cellrowborder" valign="top" width="42.77%" headers="mcps1.2.3.1.1 "><p id="p491968193914"><a name="p491968193914"></a><a name="p491968193914"></a>__init_array_end__</p>
</td>
<td class="cellrowborder" valign="top" width="57.230000000000004%" headers="mcps1.2.3.1.2 "><p id="p6919189393"><a name="p6919189393"></a><a name="p6919189393"></a>init_array段结束位置</p>
</td>
</tr>
</tbody>
</table>
>![](public_sys-resources/icon-note.gif) **说明:**
>调用该函数时,一定要在c++业务前。另外部分与系统资源强相关的类或接口,如std::thread,std::mutex等,在三方编译器使用的c库非musl c时,存在兼容性问题,不建议使用。
### 编程实例<a name="section994427141111"></a>
```
void app_init(void)
{
......
/* 启动阶段C++初始化 */
LOS_CppSystemInit((UINTPTR)&__init_array_start__, (UINTPTR)&__init_array_end__);
/* C++业务 */
......
}
```
此差异已折叠。
# FAT<a name="ZH-CN_TOPIC_0000001153180399"></a>
- [基本概念](#section1772629121418)
- [开发指导](#section1149072811148)
- [驱动适配](#section19174939191414)
- [开发流程](#section131211626151513)
- [编程实例](#section206071303163)
- [实例描述](#section45337345313)
- [示例代码](#section119813171539)
- [结果验证](#section7987101232311)
## 基本概念<a name="section1772629121418"></a>
FAT文件系统是File Allocation Table(文件配置表)的简称,主要包括DBR区、FAT区、DATA区三个区域。其中,FAT区各个表项记录存储设备中对应簇的信息,包括簇是否被使用、文件下一个簇的编号、是否文件结尾等。FAT文件系统有FAT12、FAT16、FAT32等多种格式,其中,12、16、32表示对应格式中FAT表项的字节数。FAT文件系统支持多种介质,特别在可移动存储介质(U盘、SD卡、移动硬盘等)上广泛使用,使嵌入式设备和Windows、Linux等桌面系统保持很好的兼容性,方便用户管理操作文件。
OpenHarmony内核支持FAT12、FAT16与FAT32三种格式的FAT文件系统,具有代码量小、资源占用小、可裁切、支持多种物理介质等特性,并且与Windows、Linux等系统保持兼容,支持多设备、多分区识别等功能。OpenHarmony内核支持硬盘多分区,可以在主分区以及逻辑分区上创建FAT文件系统。
## 开发指导<a name="section1149072811148"></a>
### 驱动适配<a name="section19174939191414"></a>
FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC存储设备的板子上运行FATFS,需要:
1、适配板端EMMC驱动,实现disk\_status、disk\_initialize、disk\_read、disk\_write、disk\_ioctl接口;
2、新增fs\_config.h文件,配置FS\_MAX\_SS(存储设备最大sector大小)、FF\_VOLUME\_STRS(分区名)等信息,例如:
```
#define FF_VOLUME_STRS "system", "inner", "update", "user"
#define FS_MAX_SS 512
#define FAT_MAX_OPEN_FILES 50
```
### 开发流程<a name="section131211626151513"></a>
>![](public_sys-resources/icon-note.gif) **说明:**
>- FATFS文件与目录操作:
> - 单个文件大小不超过4G。
> - 支持同时打开的文件数最大为FAT\_MAX\_OPEN\_FILES,文件夹数最大为FAT\_MAX\_OPEN\_DIRS。
> - 暂不支持根目录管理,文件/目录名均以分区名开头,例如“user/testfile”就是在“user”分区下名为“testfile”的文件或目录。
> - 若需要同时多次打开同一文件,必须全部使用只读方式(O\_RDONLY)。以可写方式(O\_RDWR、O\_WRONLY等)只能打开一次。
> - 读写指针未分离,例如以O\_APPEND(追加写)方式打开文件后,读指针也在文件尾,从头读文件前需要用户手动置位。
> - 暂不支持文件与目录的权限管理。
> - stat及fstat接口暂不支持查询修改时间、创建时间和最后访问时间。微软FAT协议不支持1980年以前的时间。
>- FATFS分区挂载与卸载:
> - 支持以只读属性挂载分区。当mount函数的入参为MS\_RDONLY时,所有的带有写入的接口,如write、mkdir、unlink,以及非O\_RDONLY属性的open,将均被拒绝。
> - mount支持通过MS\_REMOUNT标记修改已挂载分区的权限。
> - 在umount操作前,需确保所有目录及文件全部关闭。
> - umount2支持通过MNT\_FORCE参数强制关闭所有文件与文件夹并umount,但可能造成数据丢失,请谨慎使用。
>- FATFS支持重新划分存储设备分区、格式化分区,对应接口为fatfs\_fdisk与fatfs\_format:
> - 在fatfs\_format操作之前,若需要格式化的分区已挂载,需确保分区中的所有目录及文件全部关闭,并且分区umount。
> - 在fatfs\_fdisk操作前,需要该设备中的所有分区均已umount。
> - fatfs\_fdisk与fatfs\_format会造成设备数据丢失,请谨慎使用。
### 编程实例<a name="section206071303163"></a>
### 实例描述<a name="section45337345313"></a>
本实例实现以下功能:
1. 创建目录“user/test”
2. 在“user/test”目录下创建文件“file.txt”
3. 在文件起始位置写入“Hello OpenHarmony!”
4. 将文件内容刷入设备中
5. 设置偏移到文件起始位置
6. 读取文件内容
7. 关闭文件
8. 删除文件
9. 删除目录
### 示例代码<a name="section119813171539"></a>
前提条件:
- 系统已将MMC设备分区挂载到user目录
代码实现如下:
```
#include <stdio.h>
#include <string.h>
#include "sys/stat.h"
#include "fcntl.h"
#include "unistd.h"
#define LOS_OK 0
#define LOS_NOK -1
int FatfsTest(void)
{
int ret;
int fd = -1;
ssize_t len;
off_t off;
char dirName[20] = "user/test";
char fileName[20] = "user/test/file.txt";
char writeBuf[20] = "Hello OpenHarmony!";
char readBuf[20] = {0};
/* 创建目录“user/test” */
ret = mkdir(dirName, 0777);
if (ret != LOS_OK) {
printf("mkdir failed.\n");
return LOS_NOK;
}
/* 创建可读写文件"user/test/file.txt" */
fd = open(fileName, O_RDWR | O_CREAT, 0777);
if (fd < 0) {
printf("open file failed.\n");
return LOS_NOK;
}
/* 将writeBuf中的内容写入文件 */
len = write(fd, writeBuf, strlen(writeBuf));
if (len != strlen(writeBuf)) {
printf("write file failed.\n");
return LOS_NOK;
}
/* 将文件内容刷入存储设备中 */
ret = fsync(fd);
if (ret != LOS_OK) {
printf("fsync failed.\n");
return LOS_NOK;
}
/* 将读写指针偏移至文件头 */
off = lseek(fd, 0, SEEK_SET);
if (off != 0) {
printf("lseek failed.\n");
return LOS_NOK;
}
/* 将文件内容读出至readBuf中,读取长度为readBuf大小 */
len = read(fd, readBuf, sizeof(readBuf));
if (len != strlen(writeBuf)) {
printf("read file failed.\n");
return LOS_NOK;
}
printf("%s\n", readBuf);
/* 关闭文件 */
ret = close(fd);
if (ret != LOS_OK) {
printf("close failed.\n");
return LOS_NOK;
}
/* 删除文件"user/test/file.txt" */
ret = unlink(fileName);
if (ret != LOS_OK) {
printf("unlink failed.\n");
return LOS_NOK;
}
/* 删除目录“user/test” */
ret = rmdir(dirName);
if (ret != LOS_OK) {
printf("rmdir failed.\n");
return LOS_NOK;
}
return LOS_OK;
}
```
### 结果验证<a name="section7987101232311"></a>
编译运行得到的结果为:
```
Hello OpenHarmony!
```
# IPC<a name="ZH-CN_TOPIC_0000001124573873"></a>
- **[事件](事件.md)**
- **[互斥锁](互斥锁.md)**
- **[消息队列](消息队列.md)**
- **[信号量](信号量.md)**
# Linux内核编译与构建指导<a name="ZH-CN_TOPIC_0000001076416924"></a>
- [以hi3516dv300开源开发板+ubuntu x86主机开发环境为例](#section19369206113115)
- [开发示例1](#section19369206113115)
- [场景1:版本级编译原生方式](#section1025111193220)
- [场景2:单独编译修改后的内核](#section17446652173211)
## 以hi3516dv300开源开发板+ubuntu x86主机开发环境为例<a name="section19369206113115"></a>
## 开发示例1<a name="section19369206113115"></a>
以hi3516dv300开源开发板+ubuntu x86主机开发环境为例。
### 场景1:版本级编译原生方式<a name="section1025111193220"></a>
......
# LittleFS<a name="ZH-CN_TOPIC_0000001106260762"></a>
- **[基本概念](基本概念-21.md)**
- **[开发指导](开发指导-22.md)**
此差异已折叠。
# 内核
- [轻内核](轻内核.md)
- [OpenHarmony轻内核基础功能](OpenHarmony轻内核基础功能.md)
- [进程](进程.md)
- [线程](线程.md)
- [内存](内存.md)
- [网络](网络.md)
- [OpenHarmony轻内核文件系统](OpenHarmony轻内核文件系统.md)
- [VFS](VFS.md)
- [NFS](NFS.md)
- [RAMFS](RAMFS.md)
- [FAT](FAT.md)
- [JFFS2](JFFS2.md)
- [标准库](标准库.md)
- [标准库](标准库-0.md)
- [与Linux标准库的差异](与Linux标准库的差异.md)
- [调测](调测.md)
- [Shell介绍](Shell介绍.md)
- [Shell命令开发指导](Shell命令开发指导.md)
- [Shell命令编程实例](Shell命令编程实例.md)
- [Shell命令使用详解](Shell命令使用详解.md)
- [系统命令](系统命令.md)
- [cpup](cpup.md)
- [date](date.md)
- [dmesg](dmesg.md)
- [exec](exec.md)
- [free](free.md)
- [help](help.md)
- [hwi](hwi.md)
- [kill](kill.md)
- [log](log.md)
- [memcheck](memcheck.md)
- [oom](oom.md)
- [pmm](pmm.md)
- [reset](reset.md)
- [sem](sem.md)
- [stack](stack.md)
- [su](su.md)
- [swtmr](swtmr.md)
- [systeminfo](systeminfo.md)
- [task](task.md)
- [uname](uname.md)
- [vmm](vmm.md)
- [watch](watch.md)
- [文件命令](文件命令.md)
- [cat](cat.md)
- [cd](cd.md)
- [chgrp](chgrp.md)
- [chmod](chmod.md)
- [chown](chown.md)
- [cp](cp.md)
- [format](format.md)
- [ls](ls.md)
- [lsfd](lsfd.md)
- [mkdir](mkdir.md)
- [mount](mount.md)
- [partinfo](partinfo.md)
- [partition](partition.md)
- [pwd](pwd.md)
- [rm](rm.md)
- [rmdir](rmdir.md)
- [statfs](statfs.md)
- [sync](sync.md)
- [touch](touch.md)
- [writeproc](writeproc.md)
- [umount](umount.md)
- [网络命令](网络命令.md)
- [arp](arp.md)
- [dhclient](dhclient.md)
- [dns](dns.md)
- [ifconfig](ifconfig.md)
- [ipdebug](ipdebug.md)
- [netstat](netstat.md)
- [ntpdate](ntpdate.md)
- [ping](ping.md)
- [ping6](ping6.md)
- [telnet](telnet.md)
- [tftp](tftp.md)
- [魔法键使用方法](魔法键使用方法.md)
- [用户态异常信息说明](用户态异常信息说明.md)
- [Linux内核](Linux内核.md)
# 内核使用指南
- [轻量和小型系统内核](轻量和小型系统内核.md)
- [轻量系统内核](轻量系统内核.md)
- [基础内核](基础内核.md)
- [进程](进程.md)
- [线程](线程.md)
- [内存](内存.md)
- [网络](网络.md)
- [文件系统](文件系统.md)
- [VFS](VFS.md)
- [NFS](NFS.md)
- [RAMFS](RAMFS.md)
- [FAT](FAT.md)
- [JFFS2](JFFS2.md)
- [标准库](标准库.md)
- [标准库](标准库-0.md)
- [与Linux标准库的差异](与Linux标准库的差异.md)
- [调测](调测.md)
- [Shell介绍](Shell介绍.md)
- [Shell命令开发指导](Shell命令开发指导.md)
- [Shell命令编程实例](Shell命令编程实例.md)
- [Shell命令使用详解](Shell命令使用详解.md)
- [系统命令](系统命令.md)
- [cpup](cpup.md)
- [date](date.md)
- [dmesg](dmesg.md)
- [exec](exec.md)
- [free](free.md)
- [help](help.md)
- [hwi](hwi.md)
- [kill](kill.md)
- [log](log.md)
- [memcheck](memcheck.md)
- [oom](oom.md)
- [pmm](pmm.md)
- [reset](reset.md)
- [sem](sem.md)
- [stack](stack.md)
- [su](su.md)
- [swtmr](swtmr.md)
- [systeminfo](systeminfo.md)
- [task](task.md)
- [uname](uname.md)
- [vmm](vmm.md)
- [watch](watch.md)
- [文件命令](文件命令.md)
- [cat](cat.md)
- [cd](cd.md)
- [chgrp](chgrp.md)
- [chmod](chmod.md)
- [chown](chown.md)
- [cp](cp.md)
- [format](format.md)
- [ls](ls.md)
- [lsfd](lsfd.md)
- [mkdir](mkdir.md)
- [mount](mount.md)
- [partinfo](partinfo.md)
- [partition](partition.md)
- [pwd](pwd.md)
- [rm](rm.md)
- [rmdir](rmdir.md)
- [statfs](statfs.md)
- [sync](sync.md)
- [touch](touch.md)
- [writeproc](writeproc.md)
- [umount](umount.md)
- [网络命令](网络命令.md)
- [arp](arp.md)
- [dhclient](dhclient.md)
- [dns](dns.md)
- [ifconfig](ifconfig.md)
- [ipdebug](ipdebug.md)
- [netstat](netstat.md)
- [ntpdate](ntpdate.md)
- [ping](ping.md)
- [ping6](ping6.md)
- [telnet](telnet.md)
- [tftp](tftp.md)
- [魔法键使用方法](魔法键使用方法.md)
- [用户态异常信息说明](用户态异常信息说明.md)
- [小型系统内核](小型系统内核.md)
- [认识LiteOS-M内核](认识LiteOS-M内核.md)
- [快速入门](快速入门.md)
- [基础内核](基础内核-1.md)
- [中断管理](中断管理.md)
- [基本概念](基本概念.md)
- [开发指导](开发指导.md)
- [任务管理](任务管理.md)
- [基本概念](基本概念-2.md)
- [开发指导](开发指导-3.md)
- [内存管理](内存管理.md)
- [基本概念](基本概念-4.md)
- [静态内存](静态内存.md)
- [动态内存](动态内存.md)
- [IPC](IPC.md)
- [事件](事件.md)
- [基本概念](基本概念-5.md)
- [开发指导](开发指导-6.md)
- [互斥锁](互斥锁.md)
- [基本概念](基本概念-7.md)
- [开发指导](开发指导-8.md)
- [消息队列](消息队列.md)
- [基本概念](基本概念-9.md)
- [开发指导](开发指导-10.md)
- [信号量](信号量.md)
- [基本概念](基本概念-11.md)
- [开发指导](开发指导-12.md)
- [时间管理](时间管理.md)
- [基本概念](基本概念-13.md)
- [开发指导](开发指导-14.md)
- [软件定时器](软件定时器.md)
- [基本概念](基本概念-15.md)
- [开发指导](开发指导-16.md)
- [扩展组件](扩展组件.md)
- [C++支持](C++支持.md)
- [CPUP](CPUP.md)
- [基本概念](基本概念-17.md)
- [开发指导](开发指导-18.md)
- [文件系统](文件系统-19.md)
- [FAT](FAT-20.md)
- [LittleFS](LittleFS.md)
- [基本概念](基本概念-21.md)
- [开发指导](开发指导-22.md)
- [内核调测](内核调测.md)
- [内存调测](内存调测.md)
- [内存信息统计](内存信息统计.md)
- [内存泄漏检测](内存泄漏检测.md)
- [踩内存检测](踩内存检测.md)
- [异常调测](异常调测.md)
- [Trace调测](Trace调测.md)
- [附录](附录.md)
- [内核编码规范](内核编码规范.md)
- [基本数据结构](基本数据结构.md)
- [双向链表](双向链表.md)
- [标准库支持](标准库支持.md)
- [CMSIS支持](CMSIS支持.md)
- [POSIX支持](POSIX支持.md)
- [标准系统内核](标准系统内核.md)
- [Linux内核概述](Linux内核概述.md)
- [OpenHarmony开发板Patch使用指导](OpenHarmony开发板Patch使用指导.md)
- [Linux内核编译与构建指导](Linux内核编译与构建指导.md)
......
# Trace调测<a name="ZH-CN_TOPIC_0000001162019075"></a>
- [基本概念](#section44851752123712)
- [运行机制](#section5282148123813)
- [接口说明](#section16304193215387)
- [开发指导](#section498695853819)
- [开发流程](#section1875652316393)
- [编程实例](#section0403134913395)
- [示例代码](#section1492711418400)
- [结果验证](#section869613984012)
## 基本概念<a name="section44851752123712"></a>
Trace调测旨在帮助开发者获取内核的运行流程,各个模块、任务的执行顺序,从而可以辅助开发者定位一些时序问题或者了解内核的代码运行过程。
## 运行机制<a name="section5282148123813"></a>
内核提供一套Hook框架,将Hook点预埋在各个模块的主要流程中,开发者通过注册的形式在自己所需的Hook点上注册回调函数,当内核运行至对应流程中会由内核主动调用Hook函数,将当前流程的关键数据传递给开发者。
## 接口说明<a name="section16304193215387"></a>
OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细信息可以查看API参考。
**表 1** Trace模块接口说明
<a name="table208266479117"></a>
<table><thead align="left"><tr id="row19826947121114"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.1"><p id="p16415637105612"><a name="p16415637105612"></a><a name="p16415637105612"></a>功能分类</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.2"><p id="p11415163718562"><a name="p11415163718562"></a><a name="p11415163718562"></a>接口名</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.2.4.1.3"><p id="p1641533755612"><a name="p1641533755612"></a><a name="p1641533755612"></a>描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row082617478118"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p1082624717117"><a name="p1082624717117"></a><a name="p1082624717117"></a>Hook注册接口</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p1182654713112"><a name="p1182654713112"></a><a name="p1182654713112"></a>LOS_HookReg</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p1582614474114"><a name="p1582614474114"></a><a name="p1582614474114"></a>向指定Hook点注册回调函数</p>
</td>
</tr>
<tr id="row19470201017154"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.1 "><p id="p1747021015152"><a name="p1747021015152"></a><a name="p1747021015152"></a>Hook解注册接口</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.2 "><p id="p16470410201517"><a name="p16470410201517"></a><a name="p16470410201517"></a>LOS_HookUnReg</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.2.4.1.3 "><p id="p147021017155"><a name="p147021017155"></a><a name="p147021017155"></a>解注册当前Hook点的回调函数</p>
</td>
</tr>
</tbody>
</table>
## 开发指导<a name="section498695853819"></a>
### 开发流程<a name="section1875652316393"></a>
开启Trace调测的典型流程如下:
1. 配置Trace模块相关宏。
需要在target\_config.h头文件中修改配置:
<a name="table1078714915105"></a>
<table><thead align="left"><tr id="row1280518971010"><th class="cellrowborder" valign="top" width="27.24%" id="mcps1.1.4.1.1"><p id="p1380510912104"><a name="p1380510912104"></a><a name="p1380510912104"></a>配置项</p>
</th>
<th class="cellrowborder" valign="top" width="30.330000000000002%" id="mcps1.1.4.1.2"><p id="p08051291106"><a name="p08051291106"></a><a name="p08051291106"></a>含义</p>
</th>
<th class="cellrowborder" valign="top" width="42.43%" id="mcps1.1.4.1.3"><p id="p12805149151012"><a name="p12805149151012"></a><a name="p12805149151012"></a>设置值</p>
</th>
</tr>
</thead>
<tbody><tr id="row168052913104"><td class="cellrowborder" valign="top" width="27.24%" headers="mcps1.1.4.1.1 "><p id="p180618915101"><a name="p180618915101"></a><a name="p180618915101"></a>LOSCFG_DEBUG_HOOK</p>
</td>
<td class="cellrowborder" valign="top" width="30.330000000000002%" headers="mcps1.1.4.1.2 "><p id="p198061196105"><a name="p198061196105"></a><a name="p198061196105"></a>Trace功能的开关</p>
</td>
<td class="cellrowborder" valign="top" width="42.43%" headers="mcps1.1.4.1.3 "><p id="p1980609121010"><a name="p1980609121010"></a><a name="p1980609121010"></a>0:关闭;1:打开</p>
</td>
</tr>
</tbody>
</table>
2. 选择想要注册的Hook点,实现对应的回调函数,Hook类型清单见liteos\_m/utils/internal/los\_hook\_types.h。
3. 调用LOS\_HookReg进行函数注册。
### 编程实例<a name="section0403134913395"></a>
本实例实现功能:模拟运行时malloc、free不同大小的内存,记录每次malloc,free的行为及时序。
### 示例代码<a name="section1492711418400"></a>
示例代码如下:
```
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "los_hook.h"
#define SIZE_512 512
#define SIZE_1K 1024
#define SIZE_2K 2048
/* 回调时打印malloc出来的大小 */
void MallocRecord(void *pool, unsigned int size)
{
printf("malloc size = %u\n", size);
return;
}
/* 回调时打印free的指针地址 */
void FreeRecord(void *pool, void *ptr)
{
printf("free pool = 0x%x ptr = 0x%x\n", pool, ptr);
return;
}
void TestTrace(void)
{
char *pool1 = NULL;
char *pool2 = NULL;
char *pool3 = NULL;
char *retptr = NULL;
/* 分别为pool1,pool2,pool3分配不同大小的内存,用于区分验证 */
pool1 = (char *)malloc(SIZE_512);
if (pool1 == NULL) {
printf("pool1 malloc failed!\n");
return;
}
retptr = memset(pool1, 'a', SIZE_512);
if (retptr == NULL) {
printf("pool1 memset failed!\n");
return;
}
printf("pool1 addr = 0x%x *pool1[0] = %c\n", pool1, *pool1);
pool2 = (char *)malloc(SIZE_1K);
if (pool2 == NULL) {
printf("pool2 malloc failed!\n");
return;
}
retptr = memset(pool2, 'b', SIZE_1K);
if (retptr == NULL) {
printf("pool2 memset failed!\n");
return;
}
printf("pool2 addr = 0x%x *pool2[0] = %c\n", pool2, *pool2);
pool3 = (char *)malloc(SIZE_2K);
if (pool3 == NULL) {
printf("pool3 malloc failed!\n");
return;
}
retptr = memset(pool3, 'c', SIZE_2K);
if (retptr == NULL) {
printf("pool3 memset failed!\n");
return;
}
printf("pool3 addr = 0x%x *pool3[0] = %c\n", pool3, *pool3);
/* 按pool3, pool1, pool2的顺序释放,来检验回调函数的时序 */
free(pool3);
free(pool1);
free(pool2);
return;
}
/* 在使用Trace模块功能之前,首先进行回调函数的注册,注意回调函数的返回值都为void */
void InitTest(void)
{
printf("init hook\n");
/* 根据想要获取的Trace信息选择对应的Hook类型进行注册,具体可选Hook类型清单见liteos_m/utils/internal/los_hook_types.h */
LOS_HookReg(LOS_HOOK_TYPE_MEM_ALLOC, MallocRecord);
LOS_HookReg(LOS_HOOK_TYPE_MEM_FREE, FreeRecord);
return;
}
```
### 结果验证<a name="section869613984012"></a>
输出结果如下:
```
init hook
malloc size = 512
pool1 addr = 0x20002f44 *pool1[0] = a
malloc size = 1024
pool2 addr = 0x2000314c *pool2[0] = b
malloc size = 2048
pool3 addr = 0x20003554 *pool3[0] = c
free pool = 0x200002a4 ptr = 0x20003554
free pool = 0x200002a4 ptr = 0x20002f44
free pool = 0x200002a4 ptr = 0x2000314c
```
根据地址信息,可以看到free的顺序为pool3,pool1,pool2。
# 中断管理<a name="ZH-CN_TOPIC_0000001123863135"></a>
- **[基本概念](基本概念.md)**
- **[开发指导](开发指导.md)**
# 事件<a name="ZH-CN_TOPIC_0000001078716886"></a>
- **[基本概念](基本概念-5.md)**
- **[开发指导](开发指导-6.md)**
# 互斥锁<a name="ZH-CN_TOPIC_0000001123948099"></a>
- **[基本概念](基本概念-7.md)**
- **[开发指导](开发指导-8.md)**
# 任务管理<a name="ZH-CN_TOPIC_0000001124066565"></a>
- **[基本概念](基本概念-2.md)**
- **[开发指导](开发指导-3.md)**
# 信号量<a name="ZH-CN_TOPIC_0000001123948077"></a>
- **[基本概念](基本概念-11.md)**
- **[开发指导](开发指导-12.md)**
......@@ -2,7 +2,7 @@
- [基本概念](#section1392116583424)
- [使用场景](#section159581619194319)
- [功能](#section114001032104317)
- [接口说明](#section114001032104317)
## 基本概念<a name="section1392116583424"></a>
......@@ -14,7 +14,7 @@
针对用户态开发,OpenHarmony内核提供了一套内存系统调用接口,支持内存的申请释放、重映射、内存属性的设置等,还有C库的标准内存操作函数。
## 功能<a name="section114001032104317"></a>
## 接口说明<a name="section114001032104317"></a>
**表 1** 标准C库相关接口
......
# 内存信息统计<a name="ZH-CN_TOPIC_0000001078916690"></a>
- [基础概念](#section52691565235)
- [功能配置](#section470611682411)
- [开发指导](#section9368374243)
- [开发流程](#section679912407257)
- [编程实例](#section1025453412611)
- [示例代码](#section165277971315)
- [结果验证](#section3460102414271)
## 基础概念<a name="section52691565235"></a>
内存信息包括内存池大小、内存使用量、剩余内存大小、最大空闲内存、内存水线、内存节点数统计、碎片率等。
- 内存水线:即内存池的最大使用量,每次申请和释放时,都会更新水线值,实际业务可根据该值,优化内存池大小;
- 碎片率:衡量内存池的碎片化程度,碎片率高表现为内存池剩余内存很多,但是最大空闲内存块很小,可以用公式(fragment=100-最大空闲内存块大小/剩余内存大小)来度量;
- 其他参数:通过调用接口(详见[内存管理](内存管理.md)章节接口说明),扫描内存池的节点信息,统计出相关信息。
## 功能配置<a name="section470611682411"></a>
LOSCFG\_MEM\_WATERLINE:开关宏,默认打开;若关闭这个功能,在target\_config.h中将这个宏定义为0。如需获取内存水线,需要打开该配置。
## 开发指导<a name="section9368374243"></a>
### 开发流程<a name="section679912407257"></a>
关键结构体介绍:
```
typedef struct {
UINT32 totalUsedSize; // 内存池的内存使用量
UINT32 totalFreeSize; // 内存池的剩余内存大小
UINT32 maxFreeNodeSize; // 内存池的最大空闲内存块大小
UINT32 usedNodeNum; // 内存池的非空闲内存块个数
UINT32 freeNodeNum; // 内存池的空闲内存块个数
#if (LOSCFG_MEM_WATERLINE == 1) // 默认打开,如需关闭,在target_config.h中将该宏设置为0
UINT32 usageWaterLine; // 内存池的水线值
#endif
} LOS_MEM_POOL_STATUS;
```
- 内存水线获取:调用LOS\_MemInfoGet接口,第1个参数是内存池首地址,第2个参数是LOS\_MEM\_POOL\_STATUS类型的句柄,其中字段usageWaterLine即水线值。
- 内存碎片率计算:同样调用LOS\_MemInfoGet接口,可以获取内存池的剩余内存大小和最大空闲内存块大小,然后根据公式(fragment=100-最大空闲内存块大小/剩余内存大小)得出此时的动态内存池碎片率。
### 编程实例<a name="section1025453412611"></a>
本实例实现如下功能:
1.创建一个监控线程,用于获取内存池的信息;
2.调用LOS\_MemInfoGet接口,获取内存池的基础信息;
3.利用公式算出使用率及碎片率。
### 示例代码<a name="section165277971315"></a>
代码实现如下:
```
#include <stdio.h>
#include <string.h>
#include "los_task.h"
#include "los_memory.h"
#include "los_config.h"
void MemInfoTaskFunc(void)
{
LOS_MEM_POOL_STATUS poolStatus = {0};
LOS_MemInfoGet(pool, &poolStatus);
/* 算出内存池当前的碎片率百分比 */
unsigned char fragment = 100 - poolStatus.maxFreeNodeSize * 100 / poolStatus.totalFreeSize;
/* 算出内存池当前的使用率百分比 */
unsigned char usage = LOS_MemTotalUsedGet(pool) * 100 / LOS_MemPoolSizeGet(pool);
printf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize,
poolStatus.totalFreeSize, poolStatus.usageWaterLine);
}
int MemTest(void)
{
unsigned int ret;
unsigned int taskID;
TSK_INIT_PARAM_S taskStatus = {0};
taskStatus.pfnTaskEntry = (TSK_ENTRY_FUNC)MemInfoTaskFunc;
taskStatus.uwStackSize = 0x1000;
taskStatus.pcName = "memInfo";
taskStatus.usTaskPrio = 10;
ret = LOS_TaskCreate(&taskID, &taskStatus);
if (ret != LOS_OK) {
printf("task create failed\n");
return -1;
}
return 0;
}
```
### 结果验证<a name="section3460102414271"></a>
编译运行输出的结果如下:
```
usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414
```
# 内存泄漏检测<a name="ZH-CN_TOPIC_0000001079076672"></a>
- [基础概念](#section1026719436293)
- [功能配置](#section13991354162914)
- [开发指导](#section95828159308)
- [开发流程](#section369844416304)
- [编程实例](#section460801313313)
- [示例代码](#section96539275311)
- [结果验证](#section20527343183119)
## 基础概念<a name="section1026719436293"></a>
内存泄漏检测机制作为内核的可选功能,用于辅助定位动态内存泄漏问题。开启该功能,动态内存机制会自动记录申请内存时的函数调用关系(下文简称LR)。如果出现泄漏,就可以利用这些记录的信息,找到内存申请的地方,方便进一步确认。
## 功能配置<a name="section13991354162914"></a>
1. LOSCFG\_MEM\_LEAKCHECK:开关宏,默认关闭;若打开这个功能,在target\_config.h中将这个宏定义为1。
2. LOSCFG\_MEM\_RECORD\_LR\_CNT:记录的LR层数,默认3层;每层LR消耗sizeof\(void \*\)字节数的内存。
3. LOSCFG\_MEM\_OMIT\_LR\_CNT:忽略的LR层数,默认4层,即从调用LOS\_MemAlloc的函数开始记录,可根据实际情况调整。为啥需要这个配置?有3点原因如下:
- LOS\_MemAlloc接口内部也有函数调用;
- 外部可能对LOS\_MemAlloc接口有封装;
- LOSCFG\_MEM\_RECORD\_LR\_CNT 配置的LR层数有限;
正确配置这个宏,将无效的LR层数忽略,就可以记录有效的LR层数,节省内存消耗。
## 开发指导<a name="section95828159308"></a>
### 开发流程<a name="section369844416304"></a>
该调测功能可以分析关键的代码逻辑中是否存在内存泄漏。开启这个功能,每次申请内存时,会记录LR信息。在需要检测的代码段前后,调用LOS\_MemUsedNodeShow接口,每次都会打印指定内存池已使用的全部节点信息,对比前后两次的节点信息,新增的节点信息就是疑似泄漏的内存节点。通过LR,可以找到具体申请的代码位置,进一步确认是否泄漏。
调用LOS\_MemUsedNodeShow接口输出的节点信息格式如下:每1行为一个节点信息;第1列为节点地址,可以根据这个地址,使用GDB等手段查看节点完整信息;第2列为节点的大小,等于节点头大小+数据域大小;第3\~5列为函数调用关系LR地址,可以根据这个值,结合汇编文件,查看该节点具体申请的位置。
```
node size LR[0] LR[1] LR[2]
0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002
0x10017848: 0xe0 0x9b02c24e 0x9b02c246 0x9b008ef0
0x10017928: 0x50 0x9b008ed0 0x9b068902 0x9b0687c4
0x10017978: 0x24 0x9b008ed0 0x9b068924 0x9b0687c4
0x1001799c: 0x30 0x9b02c24e 0x9b02c246 0x9b008ef0
0x100179cc: 0x5c 0x9b02c24e 0x9b02c246 0x9b008ef0
```
>![](public_sys-resources/icon-caution.gif) **注意:**
>开启内存检测会影响内存申请的性能,且每个内存节点都会记录LR地址,内存开销也加大。
### 编程实例<a name="section460801313313"></a>
本实例实现如下功能:构建内存泄漏代码段。
1. 调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印;
2. 申请内存,但没有释放,模拟内存泄漏;
3. 再次调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印;
4. 将两次log进行对比,得出泄漏的节点信息;
5. 通过LR地址,找出泄漏的代码位置;
### 示例代码<a name="section96539275311"></a>
代码实现如下:
```
#include <stdio.h>
#include <string.h>
#include "los_memory.h"
#include "los_config.h"
void MemLeakTest(void)
{
LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR);
void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR);
}
```
### 结果验证<a name="section20527343183119"></a>
编译运行输出log如下:
```
node size LR[0] LR[1] LR[2]
0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc
0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc
0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e
0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a
0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220
node size LR[0] LR[1] LR[2]
0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc
0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc
0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e
0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a
0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220
0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6
0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000
```
对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块:
```
0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6
0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000
```
部分汇编文件如下:
```
MemLeakTest:
0x80041d4: 0xb510 PUSH {R4, LR}
0x80041d6: 0x4ca8 LDR.N R4, [PC, #0x2a0] ; g_memStart
0x80041d8: 0x0020 MOVS R0, R4
0x80041da: 0xf7fd 0xf93e BL LOS_MemUsedNodeShow ; 0x800145a
0x80041de: 0x2108 MOVS R1, #8
0x80041e0: 0x0020 MOVS R0, R4
0x80041e2: 0xf7fd 0xfbd9 BL LOS_MemAlloc ; 0x8001998
0x80041e6: 0x2108 MOVS R1, #8
0x80041e8: 0x0020 MOVS R0, R4
0x80041ea: 0xf7fd 0xfbd5 BL LOS_MemAlloc ; 0x8001998
0x80041ee: 0x0020 MOVS R0, R4
0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a
0x80041f4: 0xbd10 POP {R4, PC}
0x80041f6: 0x0000 MOVS R0, R0
```
其中,通过查找0x080041ee,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。
# 内存管理<a name="ZH-CN_TOPIC_0000001078876454"></a>
- **[基本概念](基本概念-4.md)**
- **[静态内存](静态内存.md)**
- **[动态内存](动态内存.md)**
# 内存调测<a name="ZH-CN_TOPIC_0000001079036426"></a>
内存调测方法旨在辅助定位动态内存相关问题,提供了基础的动态内存池信息统计手段,向用户呈现内存池水线、碎片率等信息;提供了内存泄漏检测手段,方便用户准确定位存在内存泄漏的代码行,也可以辅助分析系统各个模块内存的使用情况;提供了踩内存检测手段,可以辅助定位越界踩内存的场景。
- **[内存信息统计](内存信息统计.md)**
- **[内存泄漏检测](内存泄漏检测.md)**
- **[踩内存检测](踩内存检测.md)**
# 内核编码规范<a name="ZH-CN_TOPIC_0000001079036432"></a>
- [总体原则](#section9512812145915)
- [目录结构](#section1355317267017)
- [命名](#section1375364815017)
- [注释](#section1692516179119)
- [格式](#section10888536113)
- [](#section12276501124)
- [头文件](#section158507231319)
- [数据类型](#section91351731446)
- [变量](#section575493915417)
- [断言](#section13864440410)
- [函数](#section671919481745)
此规范基于业界通用的编程规范整理而成,请内核的开发人员遵守这样的编程风格。
## 总体原则<a name="section9512812145915"></a>
总体原则:
- 清晰:代码应当易于理解、易于维护、易于重构,避免晦涩语法
- 简洁:命名简短,函数紧凑
- 高效:通过使用算法、编译器优化选项或硬件资源提高程序效率
- 美观:代码风格合理、一致
在大部分情况下,开发人员应当遵从以下规范,但也有一些例外场景。如修改第三方开源代码或大量使用开源代码接口下,应当与开源代码保持一致。请依据总体原则,灵活处理。
## 目录结构<a name="section1355317267017"></a>
建议按照功能模块划分子目录,子目录再定义头文件和源文件目录。
目录名和文件名如果没有特殊的需要,采用全小写的形式,可以使用下划线(“\_”)分割。
## 命名<a name="section1375364815017"></a>
推荐使用驼峰风格,具体规则如下:
<a name="table881274918408"></a>
<table><thead align="left"><tr id="row1886484994019"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.1.4.1.1"><p id="p6864184954016"><a name="p6864184954016"></a><a name="p6864184954016"></a>类型</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.1.4.1.2"><p id="p486416495404"><a name="p486416495404"></a><a name="p486416495404"></a>命名风格</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.1.4.1.3"><p id="p18864549124011"><a name="p18864549124011"></a><a name="p18864549124011"></a>形式</p>
</th>
</tr>
</thead>
<tbody><tr id="row486494913409"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.1 "><p id="p2864184916403"><a name="p2864184916403"></a><a name="p2864184916403"></a>函数、结构体类型、枚举类型、联合体类型、typedef的类型</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.2 "><p id="p18864154944015"><a name="p18864154944015"></a><a name="p18864154944015"></a>大驼峰,或带有模块前缀的大驼峰</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.3 "><p id="p10864249124015"><a name="p10864249124015"></a><a name="p10864249124015"></a>AaaBbb</p>
<p id="p1886444919403"><a name="p1886444919403"></a><a name="p1886444919403"></a>XXX_AaaBbb</p>
</td>
</tr>
<tr id="row198643495409"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.1 "><p id="p18864174964013"><a name="p18864174964013"></a><a name="p18864174964013"></a>局部变量,函数参数,宏参数,结构体中字段,联合体中成员</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.2 "><p id="p12864204924018"><a name="p12864204924018"></a><a name="p12864204924018"></a>小驼峰</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.3 "><p id="p8864549124012"><a name="p8864549124012"></a><a name="p8864549124012"></a>aaaBBB</p>
</td>
</tr>
<tr id="row15864184913405"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.1 "><p id="p786484914014"><a name="p786484914014"></a><a name="p786484914014"></a>全局变量</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.2 "><p id="p1786544914400"><a name="p1786544914400"></a><a name="p1786544914400"></a>带“g_”前缀的小驼峰</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.3 "><p id="p1986594994013"><a name="p1986594994013"></a><a name="p1986594994013"></a>g_aaaBBB</p>
</td>
</tr>
<tr id="row48651849104017"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.1 "><p id="p8865104914407"><a name="p8865104914407"></a><a name="p8865104914407"></a>宏(不含函数式宏),枚举值,goto标签</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.2 "><p id="p186574954011"><a name="p186574954011"></a><a name="p186574954011"></a>全大写,下划线分割</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.3 "><p id="p188653494401"><a name="p188653494401"></a><a name="p188653494401"></a>AAA_BBB</p>
</td>
</tr>
<tr id="row1286516495402"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.1 "><p id="p108651749114012"><a name="p108651749114012"></a><a name="p108651749114012"></a>函数式宏</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.2 "><p id="p1586534910405"><a name="p1586534910405"></a><a name="p1586534910405"></a>全大写下划线分割,或大驼峰,或带有模块前缀的大驼峰</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.3 "><p id="p1186544904010"><a name="p1186544904010"></a><a name="p1186544904010"></a>AAA_BBB</p>
<p id="p18865174918402"><a name="p18865174918402"></a><a name="p18865174918402"></a>AaaBbb</p>
<p id="p13865174910407"><a name="p13865174910407"></a><a name="p13865174910407"></a>XXX_AaaBbb</p>
</td>
</tr>
<tr id="row6865154974017"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.1 "><p id="p6865114944011"><a name="p6865114944011"></a><a name="p6865114944011"></a>头文件防止重复的符号</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.2 "><p id="p16865134944010"><a name="p16865134944010"></a><a name="p16865134944010"></a>以下划线“_”开头以H结尾,中间为文件名的全大写并以下划线分割</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.3 "><p id="p1986520493408"><a name="p1986520493408"></a><a name="p1986520493408"></a>_AAA_H</p>
</td>
</tr>
</tbody>
</table>
内核对外API建议采用LOS\_ModuleFunc的形式,如果有宾语则建议采用前置的方式,比如:
```
LOS_TaskCreate
LOS_MuxLock
```
kernel目录下内部模块间的接口使用OsModuleFunc的形式,比如:
```
OsTaskScan
OsMuxInit
```
## 注释<a name="section1692516179119"></a>
一般的,尽量通过清晰的软件架构,良好的符号命名来提高代码可读性;然后在需要的时候,才辅以注释说明。
注释是为了帮助阅读者快速读懂代码,所以要从读者的角度出发,按需注释。
注释内容要简洁、明了、无歧义,信息全面且不冗余。
文件头部要进行注释,建议注释列出:版权说明、文件功能说明,作者、创建日期、注意事项等。
注释风格要统一,建议优先选择/\* \*/的方式,注释符与注释内容之间要有1空格,单行、多行注释风格如下:
```
/* 单行注释 */
// 单行注释
/*
* 多行注释
* 第二行
*/
// 多行注释
// 另一行
```
针对代码的注释,应该置于对应代码的上方或右方。
代码上方的注释,与代码行间无空行,保持与代码一样的缩进。
代码右边的注释,与代码之间,至少留1空格。
建议将多条连续的右侧注释对齐,比如:
```
#define CONST_A 100 /* Const A */
#define CONST_B 2000 /* Const B */
```
## 格式<a name="section10888536113"></a>
程序采用缩进风格编写,使用空格而不是制表符(’\\t’)进行缩进,每级缩进为4个空格。
换行时,函数左大括号另起一行放行首,并独占一行;其他左大括号跟随语句放行末。右大括号独占一行,除非后面跟着同一语句的剩余部分,如 do 语句中的 while,或者 if 语句的else/else if,或者逗号、分号。
一行只写一条语句。
比如:
```
struct MyType { // 跟随语句放行末,前置1空格
...
}; // 右大括号后面紧跟分号
int Foo(int a) { // 函数左大括号独占一行,放行首
if (a > 0) {
Foo(); // 一行只有一条语句
Bar();
} else { // 右大括号、"else"、以及后续的左大括号均在同一行
...
} // 右大括号独占一行
...
}
```
每行字符数不要超过 120 个,代码过长时应当换行,换行时将操作符留在行末,新行缩进一层或进行同类对齐,并将表示未结束的操作符或连接符号留在行末。
```
// 假设下面第一行已经不满足行宽要求
if (currentValue > MIN && // Good:换行后,布尔操作符放在行末
currentValue < MAX) { // Good: 与(&&)操作符的两个操作数同类对齐
DoSomething();
...
}
flashPara.flashEndAddr = flashPara.flashBaseAddr + // Good: 加号留在行末
flashPara.flashSize; // Good: 加法两个操作数对齐
// Good:函数参数放在一行
ReturnType result = FunctionName(paramName1, paramName2);
ReturnType result = FunctionName(paramName1,
paramName2,
paramName3); // Good:保持与上方参数对齐
ReturnType result = FunctionName(paramName1, paramName2,
paramName3, paramName4, paramName5); // Good:参数换行,4 空格缩进
ReturnType result = VeryVeryVeryLongFunctionName( // 行宽不满足第1个参数,直接换行
paramName1, paramName2, paramName3); // 换行后,4 空格缩进
// Good:每行的参数代表一组相关性较强的数据结构,放在一行便于理解
int result = DealWithStructLikeParams(left.x, left.y, // 表示一组相关参数
right.x, right.y); // 表示另外一组相关参数
```
包括 if/for/while/do-while 语句应使用大括号,即复合语句。
```
while (condition) {} // Good:即使循环体是空,也应使用大括号
while (condition) {
continue; // Good:continue 表示空逻辑,使用大括号
}
```
case/default 语句相对 switch 缩进一层,风格如下:
```
switch (var) {
case 0: // Good: 缩进
DoSomething1(); // Good: 缩进
break;
case 1: { // Good: 带大括号格式
DoSomething2();
break;
}
default:
break;
}
```
指针类型"\*"跟随变量或者函数名,例如:
```
int *p1; // OK
int* p2; // Bad:跟随类型
int*p3; // Bad:两边都没空格
int * p4; // Bad:两边都有空格
struct Foo *CreateFoo(void); // OK: "*"跟随函数名
特例:
char * const VERSION = "V100"; // OK: 当有 const 修饰符时,"*"两边都有空格
int Foo(const char * restrict p); // OK: 当有 restrict 修饰符时,"*"两边都有空格
sz = sizeof(int*); // OK:右侧没有变量,"*"跟随类型
```
## 宏<a name="section12276501124"></a>
定义函数式宏前,应考虑能否用函数替代。对于可替代场景,建议用函数替代宏。对于有性能需求的场景,可以使用内联函数。
定义宏时,要使用完备的括号,例如:
```
#define SUM(a, b) ((a) + (b)) // 符合本规范要求.
#define SOME_CONST 100 // Good: 单独的数字无需括号
#define ANOTHER_CONST (-1) // Good: 负数需要使用括号
#define THE_CONST SOME_CONST // Good: 单独的标识符无需括号
```
以下情况需要注意:
- 宏参数参与 '\#', '\#\#' 操作时,不要加括号;
- 宏参数参与字符串拼接时,不要加括号;
- 宏参数作为独立部分,在赋值(包括+=, -=等)操作的某一边时,可以不加括号;
- 宏参数作为独立部分,在逗号表达式,函数或宏调用列表中,可以不加括号。
```
// x 不要加括号
#define MAKE_STR(x) #x
// obj 不要加括号
#define HELLO_STR(obj) "Hello, " obj
// a, b 需要括号;而 value 可以不加括号
#define UPDATE_VALUE(value, a, b) (value = (a) + (b))
// a 需要括号;而 b 可以不加括号
#define FOO(a, b) Bar((a) + 1, b)
```
包含多条语句的函数式宏的实现语句必须放在 do-while\(0\)中。
禁止把带副作用的表达式作为参数传递给函数式宏,比如自加操作\(“a++”\)
函数式宏定义中慎用 return、goto、continue、break 等改变程序流程的语句。
禁止宏调用参数中出现预编译指令,如\#include,\#define和\#ifdef,这样做会导致未定义的行为。
宏定义不以分号结尾。
## 头文件<a name="section158507231319"></a>
头文件应当职责单一。
通常情况下,每个.c文件都应有一个相应的.h文件(并不一定同名),用于放置对外提供的函数声明、宏定义、类型定义等。如果不需要提供对外接口,可以没有对应的.h文件。
避免头文件循环依赖,如a.h 包含 b.h,b.h 包含 c.h,c.h 包含 a.h。
头文件应当自包含,即包含某个头文件,不需要引入其他头文件就可以编译。
头文件用\#define、\#ifndef、\#endif保护,防止重复包含;不要使用 \#pragma once。
禁止通过声明的方式引用外部函数接口、变量,只能通过包含头文件的方式使用其他模块或文件提供的接口。
建议按稳定度包含头文件,依次顺序为: 源码对应的头文件,C标准库,操作系统库,平台库,项目公共库,自己其他的依赖。
## 数据类型<a name="section91351731446"></a>
基础数据类型建议使用los\_compiler.h中定义的类型,比如无符号32位整数位定义为UINT32。
## 变量<a name="section575493915417"></a>
避免大量栈分配,如较大的局部数组。
谨慎使用全局变量,尽量不用或少用全局变量。
变量应当初始化后再使用。
禁止将局部变量的地址返回到其作用域以外。
指向资源句柄或描述符的变量,在资源释放后立即赋予新值(如果变量的作用域马上结束可以不赋予新值)。指向资源句柄或描述符的变量包括指针、文件描述符、socket描述符以及其它指向资源的变量。
## 断言<a name="section13864440410"></a>
断言必须使用宏定义,且只能在调试版本中生效。
断言应当看作设计约束,禁止用断言检测程序在运行期间可能导致的错误,可能发生的错误要用错误处理代码来处理。
禁止在断言内改变运行环境。
一个断言只用于检查一个错误。
## 函数<a name="section671919481745"></a>
由一个进程向另一个进程发送的数据、由应用向内核发送的数据等应当进行合法性校验,校验包括但不限于:
- 校验数据长度
- 校验数据范围
- 校验数据类型和格式
- 校验输入只包含可接受的字符(“白名单”形式)
函数应避免使用全局变量、静态局部变量和直接的I/O操作,不可避免时,应当对读写操作进行封装。
# 内核调测<a name="ZH-CN_TOPIC_0000001123763653"></a>
- **[内存调测](内存调测.md)**
- **[异常调测](异常调测.md)**
- **[Trace调测](Trace调测.md)**
# 动态内存<a name="ZH-CN_TOPIC_0000001123763647"></a>
- [运行机制](#section328282013571)
- [开发指导](#section7921151015814)
- [使用场景](#section326917198583)
- [接口说明](#section1032331584)
- [开发流程](#section07271773592)
- [编程实例](#section84931234145913)
- [结果验证](#section165233233917)
## 运行机制<a name="section328282013571"></a>
动态内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。
OpenHarmony LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下:
**图 1** 动态内存核心算法<a name="fig14558185217397"></a>
![](figures/动态内存核心算法.png "动态内存核心算法")
根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:\[4, 127\]\[2<sup>7</sup>, 2<sup>31</sup>\],如上图size class所示:
1.\[4,127\]区间的内存进行等分,如上图绿色部分所示,分为31个小区间,每个小区间对应内存块大小为4字节的倍数。每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。\[4,127\]区间的31个小区间内存对应31个比特位进行标记链表是否为空。
2. 大于127字节的空闲内存块,按照2的次幂区间大小进行空闲链表管理。总共分为24个小区间,每个小区间又等分为8个二级小区间,见上图蓝色的Size Class和Size SubClass部分。每个二级小区间对应一个空闲链表和用于标记对应空闲内存链表是否为空的一个比特位。总共24\*8=192个二级小区间,对应192个空闲链表和192个比特位进行标记链表是否为空。
例如,当有40字节的空闲内存需要插入空闲链表时,对应小区间\[40,43\],第10个空闲链表,位图标记的第10比特位。把40字节的空闲内存挂载第10个空闲链表上,并判断是否需要更新位图标记。当需要申请40字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。当有580字节的空闲内存需要插入空闲链表时,对应二级小区间\[2^9,2^9+2^6\],第31+2\*8=47个空闲链表,并使用位图的第47个比特位来标记链表是否为空。把580字节的空闲内存挂载第47个空闲链表上,并判断是否需要更新位图标记。当需要申请580字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。如果对应的空闲链表为空,则向更大的内存区间去查询是否有满足条件的空闲链表,实际计算时,会一次性查找到满足申请大小的空闲链表。
内存管理结构如下图所示:
**图 2** 动态内存管理结构图<a name="fig5395115964114"></a>
![](figures/动态内存管理结构图.png "动态内存管理结构图")
- 内存池池头部分
内存池池头部分包含内存池信息、位图标记数组和空闲链表数组。内存池信息包含内存池起始地址及堆区域总大小,内存池属性。位图标记数组有7个32位无符号整数组成,每个比特位标记对应的空闲链表是否挂载空闲内存块节点。空闲内存链表包含223个空闲内存头节点信息,每个空闲内存头节点信息维护内存节点头和空闲链表中的前驱、后继空闲内存节点。
- 内存池节点部分
包含3种类型节点:未使用空闲内存节点,已使用内存节点和尾节点。每个内存节点维护一个前序指针,指向内存池中上一个内存节点,还维护内存节点的大小和使用标记。空闲内存节点和已使用内存节点后面的内存区域是数据域,尾节点没有数据域。
## 开发指导<a name="section7921151015814"></a>
### 使用场景<a name="section326917198583"></a>
动态内存管理的主要工作是动态分配并管理用户申请到的内存区间。动态内存管理主要用于用户需要使用大小不等的内存块的场景,当用户需要使用内存时,可以通过操作系统的动态内存申请函数索取指定大小的内存块,一旦使用完毕,通过动态内存释放函数归还所占用内存,使之可以重复使用。
### 接口说明<a name="section1032331584"></a>
OpenHarmony LiteOS-M的动态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。
**表 1** 静态内存模块接口
<a name="table1415203765610"></a>
<table><thead align="left"><tr id="row134151837125611"><th class="cellrowborder" valign="top" width="12.85128512851285%" id="mcps1.2.4.1.1"><p id="p16415637105612"><a name="p16415637105612"></a><a name="p16415637105612"></a>功能分类</p>
</th>
<th class="cellrowborder" valign="top" width="29.8029802980298%" id="mcps1.2.4.1.2"><p id="p11415163718562"><a name="p11415163718562"></a><a name="p11415163718562"></a>接口名</p>
</th>
<th class="cellrowborder" valign="top" width="57.34573457345735%" id="mcps1.2.4.1.3"><p id="p1641533755612"><a name="p1641533755612"></a><a name="p1641533755612"></a>描述</p>
</th>
</tr>
</thead>
<tbody><tr id="row0415737175610"><td class="cellrowborder" rowspan="2" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p6485848217"><a name="p6485848217"></a><a name="p6485848217"></a>初始化和删除内存池</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p1448511481314"><a name="p1448511481314"></a><a name="p1448511481314"></a>LOS_MemInit</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p94857483110"><a name="p94857483110"></a><a name="p94857483110"></a>初始化一块指定的动态内存池,大小为size。</p>
</td>
</tr>
<tr id="row1841519376561"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p20485134810119"><a name="p20485134810119"></a><a name="p20485134810119"></a>LOS_MemDeInit</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p154851348113"><a name="p154851348113"></a><a name="p154851348113"></a>删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效。</p>
</td>
</tr>
<tr id="row1187514443616"><td class="cellrowborder" rowspan="4" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p19661710214"><a name="p19661710214"></a><a name="p19661710214"></a>申请、释放动态内存</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p66111714213"><a name="p66111714213"></a><a name="p66111714213"></a>LOS_MemAlloc</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p4661715214"><a name="p4661715214"></a><a name="p4661715214"></a>从指定动态内存池中申请size长度的内存。</p>
</td>
</tr>
<tr id="row1745415527441"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p116111718218"><a name="p116111718218"></a><a name="p116111718218"></a>LOS_MemFree</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1569175218"><a name="p1569175218"></a><a name="p1569175218"></a>释放从指定动态内存中申请的内存。</p>
</td>
</tr>
<tr id="row19101718144518"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p161417225"><a name="p161417225"></a><a name="p161417225"></a>LOS_MemRealloc</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p56181718219"><a name="p56181718219"></a><a name="p56181718219"></a>按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块。</p>
</td>
</tr>
<tr id="row1346314166464"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p10610171528"><a name="p10610171528"></a><a name="p10610171528"></a>LOS_MemAllocAlign</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p26171714214"><a name="p26171714214"></a><a name="p26171714214"></a>从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存。</p>
</td>
</tr>
<tr id="row28531740101112"><td class="cellrowborder" rowspan="4" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p39818810129"><a name="p39818810129"></a><a name="p39818810129"></a>获取内存池信息</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p16981986123"><a name="p16981986123"></a><a name="p16981986123"></a>LOS_MemPoolSizeGet</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p129820881212"><a name="p129820881212"></a><a name="p129820881212"></a>获取指定动态内存池的总大小。</p>
</td>
</tr>
<tr id="row34281341171114"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p0987831214"><a name="p0987831214"></a><a name="p0987831214"></a>LOS_MemTotalUsedGet</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1598889124"><a name="p1598889124"></a><a name="p1598889124"></a>获取指定动态内存池的总使用量大小。</p>
</td>
</tr>
<tr id="row112644551119"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p398208201215"><a name="p398208201215"></a><a name="p398208201215"></a>LOS_MemInfoGet</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p139815820126"><a name="p139815820126"></a><a name="p139815820126"></a>获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小。</p>
</td>
</tr>
<tr id="row1357684518110"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p3981383125"><a name="p3981383125"></a><a name="p3981383125"></a>LOS_MemPoolList</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p998148101218"><a name="p998148101218"></a><a name="p998148101218"></a>打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效。</p>
</td>
</tr>
<tr id="row14824879135"><td class="cellrowborder" rowspan="2" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p1058973361319"><a name="p1058973361319"></a><a name="p1058973361319"></a>获取内存块信息</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p989115206287"><a name="p989115206287"></a><a name="p989115206287"></a>LOS_MemFreeNodeShow</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p437618158141"><a name="p437618158141"></a><a name="p437618158141"></a>打印指定内存池的空闲内存块的大小及数量。</p>
</td>
</tr>
<tr id="row525917259143"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p0260025151415"><a name="p0260025151415"></a><a name="p0260025151415"></a>LOS_MemUsedNodeShow</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p19976124812146"><a name="p19976124812146"></a><a name="p19976124812146"></a>打印指定内存池的已使用内存块的大小及数量。</p>
</td>
</tr>
<tr id="row0715201211155"><td class="cellrowborder" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p13599202711513"><a name="p13599202711513"></a><a name="p13599202711513"></a>检查指定内存池的完整性</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p5784183891513"><a name="p5784183891513"></a><a name="p5784183891513"></a>LOS_MemIntegrityCheck</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p15644611153"><a name="p15644611153"></a><a name="p15644611153"></a>对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效。</p>
</td>
</tr>
</tbody>
</table>
>![](public_sys-resources/icon-note.gif) **说明:**
>- 由于动态内存管理需要管理控制块数据结构来管理内存,这些数据结构会额外消耗内存,故实际用户可使用内存总量小于配置项OS\_SYS\_MEM\_SIZE的大小。
>- 对齐分配内存接口LOS\_MemAllocAlign/LOS\_MemMallocAlign因为要进行地址对齐,可能会额外消耗部分内存,故存在一些遗失内存,当系统释放该对齐内存时,同时回收由于对齐导致的遗失内存。
### 开发流程<a name="section07271773592"></a>
本节介绍使用动态内存的典型场景开发流程。
1. 初始化LOS\_MemInit。
初始一个内存池后生成一个内存池控制头、尾节点EndNode,剩余的内存被标记为FreeNode内存节点。注:EndNode作为内存池末尾的节点,size为0。
1. 申请任意大小的动态内存LOS\_MemAlloc。
判断动态内存池中是否存在大于申请量大小的空闲内存块空间,若存在,则划出一块内存块,以指针形式返回,若不存在,返回NULL。如果空闲内存块大于申请量,需要对内存块进行分割,剩余的部分作为空闲内存块挂载到空闲内存链表上。
1. 释放动态内存LOS\_MemFree。
回收内存块,供下一次使用。调用LOS\_MemFree释放内存块,则会回收内存块,并且将其标记为FreeNode。在回收内存块时,相邻的FreeNode会自动合并。
### 编程实例<a name="section84931234145913"></a>
本实例执行以下步骤:
1. 初始化一个动态内存池。
2. 从动态内存池中申请一个内存块。
3. 在内存块中存放一个数据。
4. 打印出内存块中的数据。
5. 释放该内存块。
示例代码如下:
```
#include "los_memory.h"
VOID Example_DynMem(VOID)
{
UINT32 *mem = NULL;
UINT32 ret;
/*初始化内存池*/
ret = LOS_MemInit(g_testPool, TEST_POOL_SIZE);
if (LOS_OK == ret) {
printf("Mem init success!\n");
} else {
printf("Mem init failed!\n");
return;
}
/*分配内存*/
mem = (UINT32 *)LOS_MemAlloc(g_testPool, 4);
if (NULL == mem) {
printf("Mem alloc failed!\n");
return;
}
printf("Mem alloc success!\n");
/*赋值*/
*mem = 828;
printf("*mem = %d\n", *mem);
/*释放内存*/
ret = LOS_MemFree(g_testPool, mem);
if (LOS_OK == ret) {
printf("Mem free success!\n");
} else {
printf("Mem free failed!\n");
}
return;
}
```
### 结果验证<a name="section165233233917"></a>
输出结果如下:
```
Mem init success!
Mem alloc success!
*mem = 828
Mem free success!
```
# 双向链表<a name="ZH-CN_TOPIC_0000001078588390"></a>
- [基本概念](#section1990715203418)
- [功能说明](#section848334511411)
- [开发流程](#section01781261552)
- [编程实例](#section67569495514)
- [实例描述](#section48761994551)
- [示例代码](#section1280202685519)
- [结果验证](#section5811249105512)
## 基本概念<a name="section1990715203418"></a>
双向链表是指含有往前和往后两个方向的链表,即每个结点中除存放下一个节点指针外,还增加一个指向前一个节点的指针。其头指针head是唯一确定的。
从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种数据结构形式使得双向链表在查找时更加方便,特别是大量数据的遍历。由于双向链表具有对称性,能方便地完成各种插入、删除等操作,但需要注意前后方向的操作。
## 功能说明<a name="section848334511411"></a>
双向链表模块为用户提供下面几种功能,接口详细信息可以查看API参考。
<a name="table9827162254713"></a>
<table><tbody><tr id="row2089515228470"><td class="cellrowborder" valign="top" width="8.14%"><p id="p4895182214473"><a name="p4895182214473"></a><a name="p4895182214473"></a><strong id="b17895022154712"><a name="b17895022154712"></a><a name="b17895022154712"></a><span>功能分类</span></strong></p>
</td>
<td class="cellrowborder" valign="top" width="32.09%"><p id="p58951922124713"><a name="p58951922124713"></a><a name="p58951922124713"></a><strong id="b15895132214476"><a name="b15895132214476"></a><a name="b15895132214476"></a><span>接口名</span></strong></p>
</td>
<td class="cellrowborder" valign="top" width="59.77%"><p id="p5895122134719"><a name="p5895122134719"></a><a name="p5895122134719"></a><strong id="b5895132214471"><a name="b5895132214471"></a><a name="b5895132214471"></a><span>描述</span></strong></p>
</td>
</tr>
<tr id="row20895152284710"><td class="cellrowborder" rowspan="2" valign="top" width="8.14%"><p id="p18951922144714"><a name="p18951922144714"></a><a name="p18951922144714"></a><span>初始化链表</span></p>
</td>
<td class="cellrowborder" valign="top" width="32.09%"><p id="p789516220474"><a name="p789516220474"></a><a name="p789516220474"></a><span>LOS_ListInit</span></p>
</td>
<td class="cellrowborder" valign="top" width="59.77%"><p id="p38951422144710"><a name="p38951422144710"></a><a name="p38951422144710"></a><span>将指定双向链表节点初始化为双向链表</span></p>
</td>
</tr>
<tr id="row289552216475"><td class="cellrowborder" valign="top"><p id="p11895222194718"><a name="p11895222194718"></a><a name="p11895222194718"></a><span>LOS_DL_LIST_HEAD</span></p>
</td>
<td class="cellrowborder" valign="top"><p id="p3895222184710"><a name="p3895222184710"></a><a name="p3895222184710"></a>定义一个双向链表节点并以该节点初始化为双向链表</p>
</td>
</tr>
<tr id="row1689522210476"><td class="cellrowborder" rowspan="2" valign="top" width="8.14%"><p id="p12896132294720"><a name="p12896132294720"></a><a name="p12896132294720"></a><span>增加节点</span></p>
</td>
<td class="cellrowborder" valign="top" width="32.09%"><p id="p789611221477"><a name="p789611221477"></a><a name="p789611221477"></a><span>LOS_ListAdd</span></p>
</td>
<td class="cellrowborder" valign="top" width="59.77%"><p id="p9896122134715"><a name="p9896122134715"></a><a name="p9896122134715"></a><span>将指定节点插入到双向链表头端</span></p>
</td>
</tr>
<tr id="row188961225475"><td class="cellrowborder" valign="top"><p id="p18961122154718"><a name="p18961122154718"></a><a name="p18961122154718"></a><span>LOS_ListTailInsert</span></p>
</td>
<td class="cellrowborder" valign="top"><p id="p188961322144712"><a name="p188961322144712"></a><a name="p188961322144712"></a><span>将指定节点插入到双向链表尾端</span></p>
</td>
</tr>
<tr id="row5896112264710"><td class="cellrowborder" rowspan="2" valign="top" width="8.14%"><p id="p28961122174717"><a name="p28961122174717"></a><a name="p28961122174717"></a><span>删除节点</span></p>
</td>
<td class="cellrowborder" valign="top" width="32.09%"><p id="p28961422154710"><a name="p28961422154710"></a><a name="p28961422154710"></a><span>LOS_ListDelete</span></p>
</td>
<td class="cellrowborder" valign="top" width="59.77%"><p id="p289610224473"><a name="p289610224473"></a><a name="p289610224473"></a><span>将指定节点从链表中删除</span></p>
</td>
</tr>
<tr id="row3896522124711"><td class="cellrowborder" valign="top"><p id="p0896152213471"><a name="p0896152213471"></a><a name="p0896152213471"></a><span>LOS_ListDelInit</span></p>
</td>
<td class="cellrowborder" valign="top"><p id="p48965226475"><a name="p48965226475"></a><a name="p48965226475"></a><span>将指定节点从链表中删除,并使用该节点初始化链表</span></p>
</td>
</tr>
<tr id="row1689602294714"><td class="cellrowborder" valign="top" width="8.14%"><p id="p18961222164716"><a name="p18961222164716"></a><a name="p18961222164716"></a><span>判断双向链表是否为空</span></p>
</td>
<td class="cellrowborder" valign="top" width="32.09%"><p id="p78961522184715"><a name="p78961522184715"></a><a name="p78961522184715"></a><span>LOS_ListEmpty</span></p>
</td>
<td class="cellrowborder" valign="top" width="59.77%"><p id="p16896172254720"><a name="p16896172254720"></a><a name="p16896172254720"></a><span>判断链表是否为空</span></p>
</td>
</tr>
<tr id="row128977221474"><td class="cellrowborder" rowspan="2" valign="top" width="8.14%"><p id="p138971322174717"><a name="p138971322174717"></a><a name="p138971322174717"></a><span>获取结构体信息</span></p>
</td>
<td class="cellrowborder" valign="top" width="32.09%"><p id="p138971922194712"><a name="p138971922194712"></a><a name="p138971922194712"></a><span>LOS_DL_LIST_ENTRY</span></p>
</td>
<td class="cellrowborder" valign="top" width="59.77%"><p id="p08971022144720"><a name="p08971022144720"></a><a name="p08971022144720"></a><span>获取包含链表的结构体地址,接口的第一个入参表示的是链表中的某个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称</span></p>
</td>
</tr>
<tr id="row17897102264718"><td class="cellrowborder" valign="top"><p id="p1889792218473"><a name="p1889792218473"></a><a name="p1889792218473"></a><span>LOS_OFF_SET_OF</span></p>
</td>
<td class="cellrowborder" valign="top"><p id="p1897822194713"><a name="p1897822194713"></a><a name="p1897822194713"></a><span>获取指定结构体内的成员相对于结构体起始地址的偏移量</span></p>
</td>
</tr>
<tr id="row4897192254715"><td class="cellrowborder" rowspan="2" valign="top" width="8.14%"><p id="p3897922164714"><a name="p3897922164714"></a><a name="p3897922164714"></a><span>遍历双向链表</span></p>
</td>
<td class="cellrowborder" valign="top" width="32.09%"><p id="p58971222194713"><a name="p58971222194713"></a><a name="p58971222194713"></a><span>LOS_DL_LIST_FOR_EACH</span></p>
</td>
<td class="cellrowborder" valign="top" width="59.77%"><p id="p28971222194714"><a name="p28971222194714"></a><a name="p28971222194714"></a><span>遍历双向链表</span></p>
</td>
</tr>
<tr id="row589792254710"><td class="cellrowborder" valign="top"><p id="p689792264718"><a name="p689792264718"></a><a name="p689792264718"></a><span>LOS_DL_LIST_FOR_EACH_SAFE</span></p>
</td>
<td class="cellrowborder" valign="top"><p id="p148975222479"><a name="p148975222479"></a><a name="p148975222479"></a><span>遍历双向链表,并存储当前节点的后继节点用于安全校验</span></p>
</td>
</tr>
<tr id="row208971622174718"><td class="cellrowborder" rowspan="2" valign="top" width="8.14%"><p id="p168977224474"><a name="p168977224474"></a><a name="p168977224474"></a><span>遍历包含双向链表的结构体</span></p>
</td>
<td class="cellrowborder" valign="top" width="32.09%"><p id="p1489752216479"><a name="p1489752216479"></a><a name="p1489752216479"></a><span>LOS_DL_LIST_FOR_EACH_ENTRY</span></p>
</td>
<td class="cellrowborder" valign="top" width="59.77%"><p id="p10897522194717"><a name="p10897522194717"></a><a name="p10897522194717"></a><span>遍历指定双向链表,获取包含该链表节点的结构体地址</span></p>
</td>
</tr>
<tr id="row10897622104713"><td class="cellrowborder" valign="top"><p id="p2897112215478"><a name="p2897112215478"></a><a name="p2897112215478"></a><span>LOS_DL_LIST_FOR_EACH_ENTRY_SAFE</span></p>
</td>
<td class="cellrowborder" valign="top"><p id="p13898102220475"><a name="p13898102220475"></a><a name="p13898102220475"></a><span>遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址</span></p>
</td>
</tr>
</tbody>
</table>
## 开发流程<a name="section01781261552"></a>
双向链表的典型开发流程:
1. 调用LOS\_ListInit/LOS\_DL\_LIST\_HEAD初始双向链表。
2. 调用LOS\_ListAdd向链表插入节点。
3. 调用LOS\_ListTailInsert向链表尾部插入节点。
4. 调用LOS\_ListDelete删除指定节点。
5. 调用LOS\_ListEmpty判断链表是否为空。
6. 调用LOS\_ListDelInit删除指定节点并以此节点初始化链表。
>![](public_sys-resources/icon-note.gif) **说明:**
>- 需要注意节点指针前后方向的操作。
>- 链表操作接口,为底层接口,不对入参进行判空,需要使用者确保传参合法。
>- 如果链表节点的内存是动态申请的,删除节点时,要注意释放内存。
## 编程实例<a name="section67569495514"></a>
### 实例描述<a name="section48761994551"></a>
本实例实现如下功能:
1. 初始化双向链表。
2. 增加节点。
3. 删除节点。
4. 测试操作是否成功。
### 示例代码<a name="section1280202685519"></a>
示例代码如下:
```
#include "stdio.h"
#include "los_list.h"
static UINT32 ListSample(VOID)
{
LOS_DL_LIST listHead = {NULL,NULL};
LOS_DL_LIST listNode1 = {NULL,NULL};
LOS_DL_LIST listNode2 = {NULL,NULL};
//首先初始化链表
printf("Initial head\n");
LOS_ListInit(&listHead);
//添加节点1和节点2,并校验他们的相互关系
LOS_ListAdd(&listHead, &listNode1);
if (listNode1.pstNext == &listHead && listNode1.pstPrev == &listHead) {
printf("Add listNode1 success\n");
}
LOS_ListTailInsert(&listHead, &listNode2);
if (listNode2.pstNext == &listHead && listNode2.pstPrev == &listNode1) {
printf("Tail insert listNode2 success\n");
}
//删除两个节点
LOS_ListDelete(&listNode1);
LOS_ListDelete(&listNode2);
//确认链表为空
if (LOS_ListEmpty(&listHead)) {
printf("Delete success\n");
}
return LOS_OK;
}
```
### 结果验证<a name="section5811249105512"></a>
编译运行得到的结果为:
```
Initial head
Add listNode1 success
Tail insert listNode2 success
Delete success
```
# 基本数据结构<a name="ZH-CN_TOPIC_0000001123863115"></a>
- **[双向链表](双向链表.md)**
# 基本概念<a name="ZH-CN_TOPIC_0000001124066587"></a>
- [运行机制](#section1794010261861)
- [信号量控制块](#section11372149164815)
- [信号量运作原理](#section139726510491)
信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。
一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数,其值的含义分两种情况:
- 0,表示该信号量当前不可获取,因此可能存在正在等待该信号量的任务。
- 正值,表示该信号量当前可被获取。
以同步为目的的信号量和以互斥为目的的信号量在使用上有如下不同:
- 用作互斥时,初始信号量计数值不为0,表示可用的共享资源个数。在需要使用共享资源前,先获取信号量,然后使用一个共享资源,使用完毕后释放信号量。这样在共享资源被取完,即信号量计数减至0时,其他需要获取信号量的任务将被阻塞,从而保证了共享资源的互斥访问。另外,当共享资源数为1时,建议使用二值信号量,一种类似于互斥锁的机制。
- 用作同步时,初始信号量计数值为0。任务1获取信号量而阻塞,直到任务2或者某中断释放信号量,任务1才得以进入Ready或Running态,从而达到了任务间的同步。
## 运行机制<a name="section1794010261861"></a>
### 信号量控制块<a name="section11372149164815"></a>
```
/**
* 信号量控制块数据结构
*/
typedef struct {
UINT16 semStat; /* 信号量状态 */
UINT16 semType; /* 信号量类型 */
UINT16 semCount; /* 信号量计数 */
UINT16 semId; /* 信号量索引号 */
LOS_DL_LIST semList; /* 挂接阻塞于该信号量的任务 */
} LosSemCB;
```
### 信号量运作原理<a name="section139726510491"></a>
信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,通过LOSCFG\_BASE\_IPC\_SEM\_LIMIT宏实现),并把所有信号量初始化成未使用,加入到未使用链表中供系统使用。
信号量创建,从未使用的信号量链表中获取一个信号量,并设定初值。
信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。
信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。
信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。
信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。当访问资源的任务数达到该资源允许的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。
**图 1** 信号量运作示意图<a name="fig467314634214"></a>
![](figures/信号量运作示意图.png "信号量运作示意图")
# 基本概念<a name="ZH-CN_TOPIC_0000001078876456"></a>
时间管理以系统时钟为基础,给应用程序提供所有和时间有关的服务。
系统时钟是由定时器/计数器产生的输出脉冲触发中断产生的,一般定义为整数或长整数。输出脉冲的周期叫做一个“时钟滴答”。系统时钟也称为时标或者Tick。
用户以秒、毫秒为单位计时,而操作系统以Tick为单位计时,当用户需要对系统进行操作时,例如任务挂起、延时等,此时需要时间管理模块对Tick和秒/毫秒进行转换。
OpenHarmony LiteOS-M内核时间管理模块提供时间转换、统计功能。
### 时间单位:<a name="section1368151114500"></a>
- Cycle
系统最小的计时单位。Cycle的时长由系统主时钟频率决定,系统主时钟频率就是每秒钟的Cycle数。
- Tick
Tick是操作系统的基本时间单位,由用户配置的每秒Tick数决定。
此差异已折叠。
# 基本概念<a name="ZH-CN_TOPIC_0000001123948105"></a>
- [运行机制](#section96644177124)
CPU(中央处理器,Central Processing Unit)占用率分为系统CPU占用率和任务CPU占用率。
系统CPU占用率(CPU Percent)是指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系统CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示系统满负荷运转。
任务CPU占用率指单个任务的CPU占用率,用于表示单个任务在一段时间内的闲忙程度。任务CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示在一段时间内系统一直在运行该任务。
用户通过系统级的CPU占用率,判断当前系统负载是否超出设计规格。
通过系统中各个任务的CPU占用情况,判断各个任务的CPU占用率是否符合设计的预期。
## 运行机制<a name="section96644177124"></a>
OpenHarmony LiteOS-M的CPUP(CPU Percent,系统CPU占用率)采用任务级记录的方式,在任务切换时,记录任务启动时间,任务切出或者退出时间,每次当任务退出时,系统会累加整个任务的占用时间。
可以在target\_config.h的中对该功能进行选配。
OpenHarmony LiteOS-M提供以下两种CPU占用率的信息查询:
- 系统CPU占用率。
- 任务CPU占用率。
**CPU占用率的计算方法:**
系统CPU占用率=系统中除idle任务外其他任务运行总时间/系统运行总时间
任务CPU占用率=任务运行总时间/系统运行总时间
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# OpenHarmony轻内核基础功能<a name="ZH-CN_TOPIC_0000001111199438"></a>
# 基础内核<a name="ZH-CN_TOPIC_0000001111199438"></a>
- **[进程](进程.md)**
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册