• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 标准库
2
3
4OpenHarmony内核使用musl libc库,支持标准POSIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。
5
6
7## 标准库接口框架
8
9  **图1** POSIX接口框架
10
11  ![zh-cn_image_0000001172904117](figures/zh-cn_image_0000001172904117.png)
12
13musl libc库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony内核适配支持 ,以满足接口对外描述的功能要求。
14
15标准库支持接口的详细情况请参考C库的API文档,其中也涵盖了与POSIX标准之间的差异说明。
16
17
18### 编程实例
19
20
21####  实例描述
22
23在本示例中,主线程创建了THREAD_NUM个子线程,每个子线程启动后等待被主线程唤醒,主线程成功唤醒所有子线程后,子线程继续执行直至生命周期结束,同时主线程通过pthread_join方法等待所有线程执行结束。
24
25####  编程示例
26
27本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数ExamplePosix。
28
29示例代码如下:
30
31```
32#include <stdio.h>
33#include <unistd.h>
34#include <pthread.h>
35
36#define THREAD_NUM 3
37int g_startNum = 0; /* 启动的线程数 */
38int g_wakenNum = 0; /* 唤醒的线程数 */
39
40struct testdata {
41    pthread_mutex_t mutex;
42    pthread_cond_t cond;
43} g_td;
44
45/* 子线程入口函数 */
46static VOID *ChildThreadFunc(VOID *arg)
47{
48    int rc;
49    pthread_t self = pthread_self();
50
51    /* 获取mutex锁 */
52    rc = pthread_mutex_lock(&g_td.mutex);
53    if (rc != 0) {
54        dprintf("ERROR:take mutex lock failed, error code is %d!\n", rc);
55        goto EXIT;
56    }
57
58    /* g_startNum计数加一,用于统计已经获得mutex锁的子线程个数 */
59    g_startNum++;
60
61    /* 等待cond条件变量 */
62    rc = pthread_cond_wait(&g_td.cond, &g_td.mutex);
63    if (rc != 0) {
64        dprintf("ERROR: pthread condition wait failed, error code is %d!\n", rc);
65        (void)pthread_mutex_unlock(&g_td.mutex);
66        goto EXIT;
67    }
68
69    /* 尝试获取mutex锁,正常场景,此处无法获取锁 */
70    rc = pthread_mutex_trylock(&g_td.mutex);
71    if (rc == 0) {
72        dprintf("ERROR: mutex gets an abnormal lock!\n");
73        goto EXIT;
74    }
75
76    /* g_wakenNum计数加一,用于统计已经被cond条件变量唤醒的子线程个数 */
77    g_wakenNum++;
78
79    /* 释放mutex锁 */
80    rc = pthread_mutex_unlock(&g_td.mutex);
81    if (rc != 0) {
82        dprintf("ERROR: mutex release failed, error code is %d!\n", rc);
83        goto EXIT;
84    }
85EXIT:
86    return NULL;
87}
88
89static int ExamplePosix(VOID)
90{
91    int i, rc;
92    pthread_t thread[THREAD_NUM];
93
94    /* 初始化mutex锁 */
95    rc = pthread_mutex_init(&g_td.mutex, NULL);
96    if (rc != 0) {
97        dprintf("ERROR: mutex init failed, error code is %d!\n", rc);
98        goto ERROROUT;
99    }
100
101    /* 初始化cond条件变量 */
102    rc = pthread_cond_init(&g_td.cond, NULL);
103    if (rc != 0) {
104        dprintf("ERROR: pthread condition init failed, error code is %d!\n", rc);
105        goto ERROROUT;
106    }
107
108    /* 批量创建THREAD_NUM个子线程 */
109    for (i = 0; i < THREAD_NUM; i++) {
110        rc = pthread_create(&thread[i], NULL, ChildThreadFunc, NULL);
111        if (rc != 0) {
112            dprintf("ERROR: pthread create failed, error code is %d!\n", rc);
113            goto ERROROUT;
114        }
115    }
116    dprintf("pthread_create ok\n");
117
118    /* 等待所有子线程都完成mutex锁的获取 */
119    while (g_startNum < THREAD_NUM) {
120        usleep(100);
121    }
122
123    /* 获取mutex锁,确保所有子线程都阻塞在pthread_cond_wait上 */
124    rc = pthread_mutex_lock(&g_td.mutex);
125    if (rc != 0) {
126        dprintf("ERROR: mutex lock failed, error code is %d\n", rc);
127        goto ERROROUT;
128    }
129
130    /* 释放mutex锁 */
131    rc = pthread_mutex_unlock(&g_td.mutex);
132    if (rc != 0) {
133        dprintf("ERROR: mutex unlock failed, error code is %d!\n", rc);
134        goto ERROROUT;
135    }
136
137    for (int j = 0; j < THREAD_NUM; j++) {
138        /* 在cond条件变量上广播信号 */
139        rc = pthread_cond_signal(&g_td.cond);
140        if (rc != 0) {
141            dprintf("ERROR: pthread condition failed, error code is %d!\n", rc);
142            goto ERROROUT;
143        }
144    }
145
146    sleep(1);
147
148    /* 检查是否所有子线程都已被唤醒 */
149    if (g_wakenNum != THREAD_NUM) {
150        dprintf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum);
151        goto ERROROUT;
152    }
153    dprintf("all threads awaked\n");
154
155    /* join所有子线程,即等待其结束 */
156    for (i = 0; i < THREAD_NUM; i++) {
157        rc = pthread_join(thread[i], NULL);
158        if (rc != 0) {
159            dprintf("ERROR: pthread join failed, error code is %d!\n", rc);
160            goto ERROROUT;
161        }
162    }
163    dprintf("all threads join ok\n");
164
165    /* 销毁cond条件变量 */
166    rc = pthread_cond_destroy(&g_td.cond);
167    if (rc != 0) {
168        dprintf("ERROR: pthread condition destroy failed, error code is %d!\n", rc);
169        goto ERROROUT;
170    }
171    return 0;
172ERROROUT:
173    return -1;
174}
175```
176
177#### 验证结果
178
179  输出结果如下:
180
181```
182pthread_create ok
183all threads awaked
184all threads join ok
185```
186
187## 与Linux标准库差异
188
189本节描述了OpenHarmony内核承载的标准库与Linux标准库之间存在的关键差异。更多差异详见C库API文档说明。
190
191
192### 进程
193
1941. OpenHarmony用户态**进程**优先级只支持静态优先级且用户态可配置的优先级范围为10(最高优先级)-31(最低优先级)。
195
1962. OpenHarmony用户态**线程**优先级只支持静态优先级且用户态可配置的优先级范围为0(最高优先级)-31(最低优先级)。
197
1983. OpenHarmony进程调度策略只支持SCHED_RR, 线程调度策略支持SCHED_RR和SCHED_FIFO。
199
200
201### 内存
202
203**与Linux mmap的差异**
204
205mmap接口原型为:void \*mmap (void \*addr, size_t length, int prot, int flags, int fd, off_t offset)。
206
207其中,参数fd的生命周期实现与Linux glibc存在差异。具体体现在,glibc在成功调用mmap进行映射后,可以立即释放fd句柄。在OpenHarmony内核中,不允许用户在映射成功后立即关闭相关fd,只允许在取消映射munmap后再进行fd的close操作。如果用户不进行fd的close操作,操作系统将在进程退出时对该fd进行回收。
208
209**代码举例**
210
211
212Linux目前支持的情况如下:
213
214```
215int main(int argc, char *argv[])
216{
217    int fd;
218    void *addr = NULL;
219    ...
220    fd = open(argv[1], O_RDONLY);
221    if (fd == -1){
222        perror("open");
223        exit(EXIT_FAILURE);
224    }
225    addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, offset);
226    if (addr == MAP_FAILED) {
227        perror("mmap");
228        exit(EXIT_FAILURE);
229    }
230    close(fd);  /* OpenHarmony does not support closing fd immediately after the mapping is successful. */
231    ...
232    exit(EXIT_SUCCESS);
233}
234```
235
236
237  OpenHarmony支持的情况如下:
238
239```
240int main(int argc, char *argv[])
241{
242    int fd;
243    void *addr = NULL;
244    ...
245    fd = open(argv[1], O_RDONLY);
246    if (fd == -1) {
247        perror("open");
248        exit(EXIT_FAILURE);
249    }
250    addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, offset);
251    if (addr == MAP_FAILED) {
252        perror("mmap");
253        exit(EXIT_FAILURE);
254    }
255    ...
256    munmap(addr, length);
257    close(fd);  /* Close fd after the munmap is canceled. */
258    exit(EXIT_SUCCESS);
259}
260```
261
262
263### 文件系统
264
265**系统目录**:用户无权限修改系统目录和设备挂载目录。包含/dev,/proc,/app,/bin,/data,/etc,/lib,/system,/usr目录。
266
267**用户目录**:用户可以在该目录下进行文件创建、读写,但**不能进行设备挂载**。用户目录指/storage目录。
268
269除**系统目录**与**用户目录**之外,用户可以自行创建文件夹进行设备的挂载。但是要注意,已挂载的文件夹及其子文件夹不允许重复或者嵌套挂载,非空文件夹不允许挂载。
270
271
272### 信号
273
274- 信号默认行为不支持STOP、CONTINUE、COREDUMP功能。
275
276- 无法通过信号唤醒正在睡眠状态(举例:进程调用sleep函数进入睡眠)的进程。原因:信号机制无唤醒功能,当且仅当进程被CPU调度运行时才能处理信号内容。
277
278- 进程退出后会发送SIGCHLD给父进程,发送动作无法取消。
279
280- 信号仅支持1-30号信号,接收方收到多次同一信号,仅执行一次回调函数。
281
282
283### Time
284
285OpenHarmony当前时间精度以tick计算,系统默认10ms/tick。sleep、timeout系列函数时间误差&lt;=20ms。
286