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