• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Standard Library
2
3
4The OpenHarmony kernel uses the musl libc library that supports the Portable Operating System Interface \(POSIX\). You can develop components and applications working on the kernel based on the POSIX.
5
6## Standard Library API Framework
7
8**Figure  1**  POSIX framework<a name="fig153258541429"></a>
9![](figures/posix-framework.png "posix-framework")
10
11The musl libc library supports POSIX standards. The OpenHarmony kernel adapts the related system call APIs to implement external functions.
12
13For details about the APIs supported by the standard library, see the API document of the C library, which also covers the differences between the standard library and the POSIX standard library.
14
15## Development Example
16
17In this example, the main thread creates  **THREAD\_NUM**  child threads. Once a child thread is started, it enters the standby state. After the main thread successfully wakes up all child threads, they continue to execute until the lifecycle ends. The main thread uses the  **pthread\_join**  method to wait until all child threads are executed.
18
19```
20#include <stdio.h>
21#include <unistd.h>
22#include <pthread.h>
23
24#ifdef __cplusplus
25#if __cplusplus
26extern "C" {
27#endif /* __cplusplus */
28#endif /* __cplusplus */
29
30#define THREAD_NUM 3
31int g_startNum = 0; /* Number of started threads */
32int g_wakenNum = 0; /* Number of wakeup threads */
33
34struct testdata {
35    pthread_mutex_t mutex;
36    pthread_cond_t cond;
37} g_td;
38
39/*
40 * Entry function of child threads.
41 */
42static void *ChildThreadFunc(void *arg)
43{
44    int rc;
45    pthread_t self = pthread_self();
46
47    /* Acquire a mutex. */
48    rc = pthread_mutex_lock(&g_td.mutex);
49    if (rc != 0) {
50        printf("ERROR:take mutex lock failed, error code is %d!\n", rc);
51        goto EXIT;
52    }
53
54    /* The value of g_startNum is increased by 1. The value indicates the number of child threads that have acquired a mutex. */
55    g_startNum++;
56
57    /* Wait for the cond variable. */
58    rc = pthread_cond_wait(&g_td.cond, &g_td.mutex);
59    if (rc != 0) {
60        printf("ERROR: pthread condition wait failed, error code is %d!\n", rc);
61        (void)pthread_mutex_unlock(&g_td.mutex);
62        goto EXIT;
63    }
64
65    /* Attempt to acquire a mutex, which is failed in normal cases. */
66    rc = pthread_mutex_trylock(&g_td.mutex);
67    if (rc == 0) {
68        printf("ERROR: mutex gets an abnormal lock!\n");
69        goto EXIT;
70    }
71
72    /* The value of g_wakenNum is increased by 1. The value indicates the number of child threads that have been woken up by the cond variable. */
73    g_wakenNum++;
74
75    /* Unlock a mutex. */
76    rc = pthread_mutex_unlock(&g_td.mutex);
77    if (rc != 0) {
78        printf("ERROR: mutex release failed, error code is %d!\n", rc);
79        goto EXIT;
80    }
81EXIT:
82    return NULL;
83}
84
85static int testcase(void)
86{
87    int i, rc;
88    pthread_t thread[THREAD_NUM];
89
90    /* Initialize a mutex. */
91    rc = pthread_mutex_init(&g_td.mutex, NULL);
92    if (rc != 0) {
93        printf("ERROR: mutex init failed, error code is %d!\n", rc);
94        goto ERROROUT;
95    }
96
97    /* Initialize the cond variable. */
98    rc = pthread_cond_init(&g_td.cond, NULL);
99    if (rc != 0) {
100        printf("ERROR: pthread condition init failed, error code is %d!\n", rc);
101        goto ERROROUT;
102    }
103
104    /* Create child threads in batches. The number is specified by THREAD_NUM. */
105    for (i = 0; i < THREAD_NUM; i++) {
106        rc = pthread_create(&thread[i], NULL, ChildThreadFunc, NULL);
107        if (rc != 0) {
108            printf("ERROR: pthread create failed, error code is %d!\n", rc);
109            goto ERROROUT;
110        }
111    }
112
113    /* Wait until all child threads lock a mutex. */
114    while (g_startNum < THREAD_NUM) {
115        usleep(100);
116    }
117
118    /* Acquire a mutex and block all threads using pthread_cond_wait. */
119    rc = pthread_mutex_lock(&g_td.mutex);
120    if (rc != 0) {
121        printf("ERROR: mutex lock failed, error code is %d\n", rc);
122        goto ERROROUT;
123    }
124
125    /* Release a mutex. */
126    rc = pthread_mutex_unlock(&g_td.mutex);
127    if (rc != 0) {
128        printf("ERROR: mutex unlock failed, error code is %d!\n", rc);
129        goto ERROROUT;
130    }
131
132    for (int j = 0; j < THREAD_NUM; j++) {
133        /* Broadcast signals on the cond variable. */
134        rc = pthread_cond_signal(&g_td.cond);
135        if (rc != 0) {
136            printf("ERROR: pthread condition failed, error code is %d!\n", rc);
137            goto ERROROUT;
138        }
139    }
140
141    sleep(1);
142
143    /* Check whether all child threads are woken up. */
144    if (g_wakenNum != THREAD_NUM) {
145        printf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum);
146        goto ERROROUT;
147    }
148
149    /* Wait for all threads to terminate. */
150    for (i = 0; i < THREAD_NUM; i++) {
151        rc = pthread_join(thread[i], NULL);
152        if (rc != 0) {
153            printf("ERROR: pthread join failed, error code is %d!\n", rc);
154            goto ERROROUT;
155        }
156    }
157
158    /* Destroy the cond variable. */
159    rc = pthread_cond_destroy(&g_td.cond);
160    if (rc != 0) {
161        printf("ERROR: pthread condition destroy failed, error code is %d!\n", rc);
162        goto ERROROUT;
163    }
164    return 0;
165ERROROUT:
166    return -1;
167}
168
169/*
170 * Main function
171 */
172int main(int argc, char *argv[])
173{
174    int rc;
175
176    /* Start the test function. */
177    rc = testcase();
178    if (rc != 0) {
179        printf("ERROR: testcase failed!\n");
180    }
181
182    return 0;
183}
184#ifdef __cplusplus
185#if __cplusplus
186}
187#endif /* __cplusplus */
188#endif /* __cplusplus */
189```
190
191## Differences from the Linux Standard Library
192
193This section describes the key differences between the standard library carried by the OpenHarmony kernel and the Linux standard library. For more differences, see the API document of the C library.
194
195### Process
196
1971.  The OpenHarmony user-mode processes support only static priorities, which range from 10 \(highest\) to 31 \(lowest\).
1982.  The OpenHarmony user-mode threads support only static priorities, which range from 0 \(highest\) to 31 \(lowest\).
1993.  The OpenHarmony process scheduling supports  **SCHED\_RR**  only, and thread scheduling supports  **SCHED\_RR**  or  **SCHED\_FIFO**.
200
201### Memory
202
203**h2****Difference with Linux mmap**
204
205mmap prototype:  **void \*mmap \(void \*addr, size\_t length, int prot, int flags, int fd, off\_t offset\)**
206
207The lifecycle implementation of  **fd**  is different from that of Linux glibc. glibc releases the  **fd**  handle immediately after successfully invoking  **mmap**  for mapping. In the OpenHarmony kernel, you are not allowed to close the  **fd**  immediately after the mapping is successful. You can close the  **fd**  only after  **munmap**  is called. If you do not close  **fd**, the OS reclaims the  **fd**  when the process exits.
208
209**h2****Sample Code**
210
211Linux OS:
212
213```
214int main(int argc, char *argv[])
215{
216    int fd;
217    void *addr = NULL;
218    ...
219    fd = open(argv[1], O_RDONLY);
220    if (fd == -1){
221        perror("open");
222        exit(EXIT_FAILURE);
223    }
224    addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, offset);
225    if (addr == MAP_FAILED) {
226        perror("mmap");
227        exit(EXIT_FAILURE);
228    }
229    close(fd); /*  OpenHarmony does not support close fd immediately after the mapping is successful. */
230    ...
231    exit(EXIT_SUCCESS);
232}
233```
234
235OpenHarmony:
236
237```
238int main(int argc, char *argv[])
239{
240    int fd;
241    void *addr = NULL;
242    ...
243    fd = open(argv[1], O_RDONLY);
244    if (fd == -1) {
245        perror("open");
246        exit(EXIT_FAILURE);
247    }
248    addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, offset);
249    if (addr == MAP_FAILED) {
250        perror("mmap");
251        exit(EXIT_FAILURE);
252    }
253    ...
254    munmap(addr, length);
255    close(fd); /* Close fd after the munmap is canceled. */
256    exit(EXIT_SUCCESS);
257}
258```
259
260### File System
261
262**System directories**: You cannot modify system directories and device mount directories, which include  **/dev**,  **/proc**,  **/app**,  **/bin**,  **/data**,  **/etc**,  **/lib**,  **/system**  and  **/usr**.
263
264**User directory**: The user directory refers to the  **/storage**  directory. You can create, read, and write files in this directory, but cannot mount devices.
265
266Except in the system and user directories, you can create directories and mount devices. Note that nested mount is not allowed, that is, a mounted folder and its subfolders cannot be mounted repeatedly. A non-empty folder cannot be mounted.
267
268### Signal
269
270-   The default behavior for signals does not include  **STOP**,  **CONTINUE**, or  **COREDUMP**.
271-   A sleeping process \(for example, a process enters the sleeping status by calling the sleep function\) cannot be woken up by a signal. The signal mechanism does not support the wakeup function. The behavior for a signal can be processed only when the process is scheduled by the CPU.
272-   After a process exits,  **SIGCHLD**  is sent to the parent process. The sending action cannot be canceled.
273-   Only signals 1 to 30 are supported. The callback is executed only once even if the same signal is received multiple times.
274
275### Time
276
277The OpenHarmony time precision is based on tick. The default value is 10 ms/tick. The time error of the  **sleep**  and  **timeout**  functions is less than or equal to 20 ms.
278
279