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 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