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