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