鸿蒙OpenHarmony【轻量系统内核(标准库支持)】子系统开发

CMSIS支持

基本概念

[CMSIS]是Cortex Microcontroller Software Interface Standard(Cortex微控制器软件接口标准)的缩写,是对于那些基于ARM Cortex处理器的微控制器独立于供应商的硬件抽象层。它包含多个组件层,其中之一是RTOS层,该层定义了一套通用及标准化的RTOS API接口,减少了应用开发者对特定RTOS的依赖,方便用户软件的移植重用。该套API有2个版本,分别为版本1(CMSIS-RTOS v1)和版本2(CMSIS-RTOS v2),OpenHarmony LiteOS-M仅提供其版本2的实现。

开发指导

接口说明

CMSIS-RTOS v2提供下面几种功能,接口详细信息可以查看API参考。

表1 内核信息与控制

接口名接口描述
osKernelGetInfo获取RTOS内核信息。
osKernelGetState获取当前的RTOS内核状态。
osKernelGetSysTimerCount获取RTOS内核系统计时器计数。
osKernelGetSysTimerFreq获取RTOS内核系统计时器频率。
osKernelInitialize初始化RTOS内核。
osKernelLock锁定RTOS内核调度程序。
osKernelUnlock解锁RTOS内核调度程序。
osKernelRestoreLock恢复RTOS内核调度程序锁定状态。
osKernelResume恢复RTOS内核调度程序。(暂未实现)
osKernelStart启动RTOS内核调度程序。
osKernelSuspend挂起RTOS内核调度程序。(暂未实现)
osKernelGetTickCount获取RTOS内核滴答计数。
osKernelGetTickFreq获取RTOS内核滴答频率。

表2 线程管理

接口名接口描述
osThreadDetach分离线程(线程终止时可以回收线程存储)。(暂未实现)
osThreadEnumerate枚举活动线程。(暂未实现)
osThreadExit终止当前正在运行的线程的执行。
osThreadGetCount获取活动线程的数量。
osThreadGetId返回当前正在运行的线程的线程ID。
osThreadGetName获取线程的名称。
osThreadGetPriority获取线程的当前优先级。
osThreadGetStackSize获取线程的堆栈大小。
osThreadGetStackSpace根据执行期间的堆栈水印记录获取线程的可用堆栈空间。
osThreadGetState获取线程的当前线程状态。
osThreadJoin等待指定线程终止。(暂未实现)
osThreadNew创建一个线程并将其添加到活动线程中。
osThreadResume恢复线程的执行。
osThreadSetPriority更改线程的优先级。
osThreadSuspend暂停执行线程。
osThreadTerminate终止线程的执行。
osThreadYield将控制权传递给处于就绪状态的下一个线程。

表3 线程标志

接口名接口描述
osThreadFlagsSet设置线程的指定线程标志。(暂未实现)
osThreadFlagsClear清除当前正在运行的线程的指定线程标志。(暂未实现)
osThreadFlagsGet获取当前正在运行的线程的当前线程标志。(暂未实现)
osThreadFlagsWait等待当前正在运行的线程的一个或多个线程标志发出信号。(暂未实现)

表4 事件标志

接口名接口描述
osEventFlagsGetName获取事件标志对象的名称。(暂未实现)
osEventFlagsNew创建并初始化事件标志对象。
osEventFlagsDelete删除事件标志对象。
osEventFlagsSet设置指定的事件标志。
osEventFlagsClear清除指定的事件标志。
osEventFlagsGet获取当前事件标志。
osEventFlagsWait等待一个或多个事件标志被发出信号。

表5 通用等待函数

接口名接口描述
osDelay等待超时(时间延迟)。
osDelayUntil等到指定时间。

表6 计时器管理

接口名接口描述
osTimerDelete删除计时器。
osTimerGetName获取计时器的名称。(暂未实现)
osTimerIsRunning检查计时器是否正在运行。
osTimerNew创建和初始化计时器。
osTimerStart启动或重新启动计时器。
osTimerStop停止计时器。

表7 互斥管理

接口名接口描述
osMutexAcquire获取互斥或超时(如果已锁定)。
osMutexDelete删除互斥对象。
osMutexGetName获取互斥对象的名称。(暂未实现)
osMutexGetOwner获取拥有互斥对象的线程。
osMutexNew创建并初始化Mutex对象。
osMutexRelease释放由osMutexAcquire获取的Mutex。

表8 信号量

接口名接口描述
osSemaphoreAcquire获取信号量令牌或超时(如果没有可用的令牌)。
osSemaphoreDelete删除一个信号量对象。
osSemaphoreGetCount获取当前信号量令牌计数。
osSemaphoreGetName获取信号量对象的名称。(暂未实现)
osSemaphoreNew创建并初始化一个信号量对象。
osSemaphoreRelease释放信号量令牌,直到初始最大计数。

表9 内存池

接口名接口描述
osMemoryPoolAlloc从内存池分配一个内存块。
osMemoryPoolDelete删除内存池对象。
osMemoryPoolFree将分配的内存块返回到内存池。
osMemoryPoolGetBlockSize获取内存池中的内存块大小。
osMemoryPoolGetCapacity获取内存池中最大的内存块数。
osMemoryPoolGetCount获取内存池中使用的内存块数。
osMemoryPoolGetName获取内存池对象的名称。
osMemoryPoolGetSpace获取内存池中可用的内存块数。
osMemoryPoolNew创建并初始化一个内存池对象。

表10 消息队列

接口名接口描述
osMessageQueueDelete删除消息队列对象。
osMessageQueueGet从队列获取消息,或者如果队列为空,则从超时获取消息。
osMessageQueueGetCapacity获取消息队列中的最大消息数。
osMessageQueueGetCount获取消息队列中排队的消息数。
osMessageQueueGetMsgSize获取内存池中的最大消息大小。
osMessageQueueGetName获取消息队列对象的名称。(暂未实现)
osMessageQueueGetSpace获取消息队列中消息的可用插槽数。
osMessageQueueNew创建和初始化消息队列对象。
osMessageQueuePut如果队列已满,则将消息放入队列或超时。
osMessageQueueReset将消息队列重置为初始空状态。(暂未实现)
开发流程

CMSIS-RTOS2组件可以作为库或源代码提供(下图显示了库)。通过添加CMSIS-RTOS2组件(通常是一些配置文件),可以将基于CMSIS的应用程序扩展为具有RTOS功能。只需包含cmsis_os2.h头文件就可以访问RTOS API函数,这使用户应用程序能够处理RTOS内核相关事件,而在更换内核时无需重新编译源代码。

静态对象分配需要访问RTOS对象控制块定义。特定于实现的头文件(下图中的os_xx .h)提供对此类控制块定义的访问。对于OpenHarmony LiteOS-M内核,由文件名以los_开头的头文件提供,这些文件包含OpenHarmony LiteOS-M内核的这些定义。

1

编程实例
#include ...
#include "cmsis_os2.h"/*----------------------------------------------------------------------------* 应用程序主线程*---------------------------------------------------------------------------*/
void app_main (void *argument) {// ...for (;;) {}
}int main (void) {// 系统初始化MySystemInit();// ...osKernelInitialize();                 // 初始化CMSIS-RTOSosThreadNew(app_main, NULL, NULL);    // 创建应用程序主线程osKernelStart();                      // 开始执行线程for (;;) {}
}

POSIX支持

基本概念

OpenHarmony内核使用musl libc库以及自研接口,支持部分标准POSIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。

开发指导

接口说明

表1 process

需要包含的头文件接口名描述
#include <stdlib.h>void abort(void);中止线程执行
#include <assert.h>void assert(scalar expression);断言为假终止线程
#include <pthread.h>int pthread_cond_destroy(pthread_cond_t *cond);销毁条件变量
#include <pthread.h>int pthread_cond_init(pthread_cond_t *restrict co nd, const pthread_condattr_t *restrict attr);初始化条件变量
#include <pthread.h>int pthread_cond_timedwait(pthread_cond_t *restr ict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);等待条件
#include <pthread.h>int pthread_condattr_init(pthread_condattr_t *attr);初始化条件变量属性对象
#include <pthread.h>int pthread_mutex_unlock(pthread_mutex_t *mutex);解锁互斥锁
#include <pthread.h>int pthread_create(pthread_t *thread, const pthread_ attr_t *attr, void *(*start_routine)(void *), void *arg);创建一个新的线程
#include <pthread.h>int pthread_join(pthread_t thread, void **retval);等待指定的线程结束
#include <pthread.h>pthread_t pthread_self(void);获取当前线程的ID
#include <pthread.h>int pthread_getschedparam(pthread_t thread, int * policy, struct sched_param *param);获取线程的调度策略和参数
#include <pthread.h>int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param);设置线程的调度策略和参数
#include <pthread.h>int pthread_mutex_init(pthread_mutex_t *__restrict m , const pthread_mutexattr_t *__restrict a);初始化互斥锁
#include <pthread.h>int pthread_mutex_lock(pthread_mutex_t *m);互斥锁加锁操作
#include <pthread.h>int pthread_mutex_trylock(pthread_mutex_t *m);互斥锁尝试加锁操作
#include <pthread.h>int pthread_mutex_destroy(pthread_mutex_t *m);销毁互斥锁
#include <pthread.h>int pthread_attr_init(pthread_attr_t *attr);初始化线程属性对象
#include <pthread.h>int pthread_attr_destroy(pthread_attr_t *attr);销毁线程属性对象
#include <pthread.h>int pthread_attr_getstacksize(const pthread_attr _t *attr, size_t *stacksize);获取线程属性对象的堆栈大小
#include <pthread.h>int pthread_attr_setstacksize(pthread_attr_t *attr , size_t stacksize);设置线程属性对象的堆栈大小
#include <pthread.h>int pthread_attr_getschedparam(const pthread_ attr_t *attr, struct sched_param *param);获取线程属性对象的调度参数属性
#include <pthread.h>int pthread_attr_setschedparam(pthread_attr_t * attr, const struct sched_param *param);设置线程属性对象的调度参数属性
#include <pthread.h>int pthread_getname_np(pthread_t pthread, char *name, size_t len);获取线程名称
#include <pthread.h>int pthread_setname_np(pthread_t pthread, const char *name);设置线程名称
#include <pthread.h>int pthread_cond_broadcast(pthread_cond_t *c);解除若干已被等待条件阻塞的线程
#include <pthread.h>int pthread_cond_signal(pthread_cond_t *c);解除被阻塞的线程
#include <pthread.h>int pthread_cond_wait(pthread_cond_t *__restrict c, pthread_mutex_t *__restrict m);等待条件

表2 fs

需要包含的头文件接口名描述
#include <libgen.h>char *dirname(char *path);获取目录名
#include <dirent.h>struct dirent *readdir(DIR *dirp);读目录
#include <sys/stat.h>int stat(const char *restrict path, struct stat *restrict buf);获取文件信息
#include <unistd.h>int unlink(const char *pathname);删除文件
#include <fcntl.hint open(const char *path, int oflags, …);用于打开文件,如文件不存在,创建文件并打开
#include <nistd.h>int close(int fd);关闭文件
#include <stdio.h>int rename(const char *oldpath, const char *newpath);重命名指定的文件
#include <dirent.h>DIR *opendir(const char *dirname);打开指定目录
#include <dirent.h>int closedir(DIR *dir);关闭指定目录
#include <sys/mount.h>int mount(const char *source, const char *target, con st char *filesystemtype, unsigned long mountflags, c onst void *data);挂载文件系统
#include <sys/mount.h>int umount(const char *target);卸载文件系统
#include <sys/mount.h>int umount2(const char *target, int flag);卸载文件系统
#include <sys/stat.h>int fsync(int fd);将与指定文件描述符关联的文件同步到存储设备
#include <sys/stat.h>int mkdir(const char *pathname, mode_t mode);创建目录
#include <unistd.h>int rmdir(const char *path);删除目录
#include <sys/stat.h>int fstat(int fd, struct stat *buf);获取文件状态信息
#include <sys/statfs.h>int statfs(const char *path, struct statfs *buf);获取指定路径下文件的文件系统信息

表3 time

需要包含的头文件接口名描述
#include <sys/time.h>int gettimeofday(struct timeval *tv, struct timezone *tz);获取时间。当前暂无时区概念,tz返回为空
#include <time.h>struct tm *gmtime(const time_t *timep);将日期和时间转换为细分时间或ASCII
#include <time.h>struct tm *localtime(const time_t *timep);获取时间
#include <time.h>struct tm *localtime_r(const time_t *timep, struct tm *result);获取时间
#include <time.h>time_t mktime(struct tm *tm);将日期和时间转换为细分时间或ASCII
#include <time.h>size_t strftime(char *s, size_t max, const char * format,const struct tm *tm);格式化日期和时间字符串
#include <time.h>time_t time(time_t *tloc);获得日历时间
#include <sys/times.h>clock_t times(struct tms *buf);获取线程时间
#include <unistd.h>int usleep(useconds_t usec);休眠(微秒单位)
#include <time.h>int nanosleep(const struct timespec *tspec1, struct timespec *tspec2);暂停当前线程直到指定的时间到达
#include <time.h>int clock_gettime(clockid_t id, struct timespec *tspec);获取时钟的时间
#include <time.h>int timer_create(clockid_t id, struct sigevent *__ restrict evp, timer_t *__restrict t);为线程创建计时器
#include <time.h>int timer_delete(timer_t t);为线程删除计时器
#include <time.h>int timer_settime(timer_t t, int flags, const struct itimerspec *__restrict val, struct itimerspec *__restrict old);为线程设置计时器
#include <time.h>time_t time (time_t *t);获取时间
#include <time.h>char *strptime(const char *s, const char *format, struct tm *tm);将时间的字符串表示形式转换为时间tm结构

表4 util

需要包含的头文件接口名描述
#include <stdlib.h>int atoi(const char *nptr);字符串转换整型(int)
#include <stdlib.h>long atol(const char *nptr);字符串转换整型(long)
#include <stdlib.h>long long atoll(const char *nptr);字符串转换整型(long long)
#include <ctype.h>int isalnum(int c);检查字母数字字符
#include <ctype.h>int isascii(int c);检查ASCII
#include <ctype.h>int isdigit(int c);检查数字字符
#include <ctype.h>int islower(int c);检查小写字符
#include <ctype.h>int isprint(int c);检查任何可打印字符,包括空格
#include <ctype.h>int isspace(int c);检查空格字符
#include <ctype.h>int isupper(int c);检查所传的字符是否是大写字母
#include <ctype.h>int isxdigit(int c);判断字符是否为十六进制数
#include <stdlib.h>long int random (void);生成伪随机数
#include <stdlib.h>void srandom(unsigned int seed);初始化随机数生成器
#include <ctype.h>int tolower(int c);字母转换成小写
#include <ctype.h>int toupper(int c);字母转换成大写
#include <stdarg.h>type va_arg(va_list ap, type);获取可变参数的当前参数,返回指定类型并将指针指向下一参数
#include <stdarg.h>void va_copy(va_list dest, va_list src);复制参数
#include <stdarg.h>void va_end(va_list ap);清空va_list可变参数列表
#include <stdarg.h>void va_start(va_list ap, last);定义变长参数列表的起始位置
#include <string.h>char *strchr(const char *s, int c);在字符串中定位字符
#include <string.h>int strcmp(const char *s1, const char *s2);比较字符串
#include <string.h>size_t strcspn(const char *s, const char *reject);获取前缀子串的长度
#include <string.h>char *strdup(const char *s);字符串拷贝到新建的位置处
#include <string.h>size_t strlen(const char *s);计算字符串长度
#include <strings.h>int strncasecmp(const char *s1, const char *s2, size_t n);比较固定长度字符串(忽略大小写)
#include <strings.h>int strcasecmp(const char *s1, const char *s2);比较字符串(忽略大小写)
#include <string.h>int strncmp(const char *s1, const char *s2, size_t n);比较字符串(指定长度)
#include <string.h>char *strrchr(const char *s, int c);在字符串中定位字符
#include <string.h>char *strstr(const char *haystack, const char *needle);寻找指定的子串
#include <stdlib.h>long int strtol(const char *nptr, char **endptr, int base);将字符串转换为long型整数
#include <stdlib.h>unsigned long int strtoul(const char *nptr, char **endptr, int base);将字符串转换为unsigned long型整数
#include <stdlib.h>unsigned long long int strtoull(const char *nptr, char **endptr,int base);将字符串转换为unsigned long long型整数
#include <regex.h>int regcomp(regex_t *preg, const char *regex, int cflags);编译正则表达式
#include <regex.h>int regexec(const regex_t *preg, const char * string, size_t nmatch,regmatch_t pmatch[], int eflags);匹配正则表达式
#include <regex.h>void regfree(regex_t *preg);释放正则表达式
#include <string.h>char *strerror(int errnum);返回描述错误号的字符串

表5 math

需要包含的头文件接口名描述
#include <stdlib.h>int abs(int i);取绝对值
#include <math.h>double log(double x);自然对数函数
#include <math.h>double pow(double x, double y);求x的指数y次幂
#include <math.h>double round(double x);从零开始,舍入到最接近的整数
#include <math.h>double sqrt(double x);平方根

表6 IO

需要包含的头文件接口名描述
#include <stdio.h>void clearerr(FILE *stream);清除流的文件结尾和错误指示
#include <stdio.h>int fclose(FILE *stream);关闭文件流
#include <stdio.h>FILE *fdopen(int fd, const char *mode);通过文件描述符打开文件流
#include <stdio.h>int feof(FILE *stream);检测返回文件末尾指示位
#include <stdio.h>int fflush(FILE *stream);刷新流
#include <stdio.h>char *fgets(char *s, int size, FILE *stream);读取流的下一行
#include <stdio.h>int fileno(FILE *stream);返回流的文件描述符
#include <stdio.h>FILE *fopen(const char *path, const char *mode);打开流
#include <stdio.h>int fputs(const char *s, FILE *stream);向指定流写入一行
#include <stdio.h>size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);读一个流
#include <stdio.h>int fseek(FILE *stream, long offset, int whence);设置流指针的位置
#include <stdio.h>long ftell(FILE *stream);获取流指针的位置
#include <stdio.h>size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);向流写入
#include <stdio.h>void perror(const char *s);打印系统错误信息
#include <stdio.h>void rewind(FILE *stream);重新定位流
#include <unistd.h>ssize_t write(int fd, const void *buf, size_t size);写文件内容
#include <unistd.h>ssize_t read(int fd, void *buf, size_t size);读文件内容

表7 net

需要包含的头文件接口名描述
#include <sys/socket.h>void freeaddrinfo(struct addrinfo *res);释放调用getaddrinfo所分配的动态内存
#include <sys/socket.h>int getaddrinfo(const char *restrict nodename,const char *restrict servname,const struct addrinfo *restrict hints,struct addrinfo **restrict res);网络地址和服务转换
#include <sys/socket.h>int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,char *restrict node, socklen_t nodelen , char *restrict service,socklen_t servicelen, int flags);以协议无关的方式进行地址到名称的转换
#include <net/if.h>unsigned int if_nametoindex(const char *ifname);通过网络接口名得到索引
#include <arpa/inet.h>in_addr_t inet_addr(const char *cp);网络主机地址点分十进制形式转换位二进制形式
#include <arpa/inet.h>char *inet_ntoa(struct in_addr in);网络主机地址二进制形式转换位点分十进制形式
#include <arpa/inet.h>const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);网络地址转换
#include <arpa/inet.h>int inet_pton(int af, const char *src, void *dst);网络地址转换
#include <sys/socket.h>int listen(int sockfd, int backlog);监听套接字
#include <sys/socket.h>ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);从套接字接收消息.只支持iov大小为1的场景,且不支持ancillary消息
#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t len, int flags);从socket发送消息
#include <sys/socket.h>ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);从socket发送消息。不支持ancillary消息
#include <sys/socket.h>ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);从socket发送消息
#include <sys/socket.h>int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);设置与套接字关联的选项

表8 mem

需要包含的头文件接口名描述
#include <string.h>int memcmp(const void *s1, const void *s2, size_t n);内存比较
#include <string.h>void *memcpy(void *dest, const void *src, size_t n);内存拷贝
#include <string.h>void *memset(void *s, int c, size_t n);内存初始化
#include <stdlib.h>void *realloc(void *ptr, size_t size);重分配内存
#include <stdlib.h>void *malloc(size_t size);动态分配内存块大小
#include <stdlib.h>void free(void *ptr);释放ptr所指向的内存空间

表9 IPC

需要包含的头文件接口名描述
#include <semaphore.h>int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);计时锁定信号量
#include <semaphore.h>int sem_destroy(sem_t *sem);销毁指定的无名信号量
#include <semaphore.h>int sem_init(sem_t *sem, int pshared , unsigned int value);创建并初始化一个无名信号量
#include <semaphore.h>int sem_post(sem_t *sem);增加信号量计数
#include <semaphore.h>int sem_wait(sem_t *sem);获取信号量
#include <mqueue.h>mqd_t mq_open(const char *mqName, int openFlag, …);此API用于打开一个具有指定名称的已有消息队列或创建一个新的消息队列
#include <mqueue.h>int mq_close(mqd_t personal);此API用于关闭具有指定描述符的消息队列
#include <mqueue.h>int mq_unlink(const char *mqName);此API用于删除具有指定名称的消息队列
#include <mqueue.h>int mq_send(mqd_t personal, const char *msg,size_t msgLen, unsigned int msgPrio);此API用于将具有指定内容和长度的消息放入具有指定描述符的消息队列中
#include <mqueue.h>ssize_t mq_receive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio);此API用于从具有指定描述符的消息队列中删除最老的消息,并将其放入msg_ptr所指向的缓冲区中
#include <mqueue.h>int mq_timedsend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio, c onst struct timespec *absTimeout)此API用于在预定时间将具有指定内容和长度的消息放入具有描述符的消息队列中
#include <mqueue.h>ssize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, const struct timespec *absTimeout);此API用于从具有指定描述符的消息队列消息中获取具有指定消息内容和长度的消息
#include <mqueue.h>int mq_setattr(mqd_t mqdes, const struct mq_ attr *__restrict newattr, struct mq_attr *__restrict oldattr);设置描述符指定的消息队列属性
#include <libc.h>const char *libc_get_version_string(void);获取libc版本字符串
#include <libc.h>int libc_get_version(void);获取libc版本号
注意事项

常用错误码对照表:

错误码描述含义
ENOERR0Success成功
EPERM1Operation not permitted操作不允许
ENOENT2No such file or directory没有这样的文件或目录
ESRCH3No such process没有这样的进程(暂不支持)
EINTR4Interrupted system call系统调用被中断
EIO5I/O errorI/O错误
ENXIO6No such device or address没有这样的设备或地址
E2BIG7Arg list too long参数列表太长
ENOEXEC8Exec format error执行格式错误
EBADF9Bad file number坏的文件描述符
ECHILD10No child processes没有子进程(暂不支持)
EAGAIN11Try again资源暂时不可用
ENOMEM12Out of memory内存溢出
EACCES13Permission denied拒绝许可
EFAULT14Bad address错误的地址
ENOTBLK15Block device required块设备请求
EBUSY16Device or resource busy设备或资源忙
EEXIST17File exists文件存在
EXDEV18Cross-device link无效的交叉链接
ENODEV19No such device设备不存在
ENOTDIR20Not a directory不是一个目录
EISDIR21Is a directory是一个目录
EINVAL22Invalid argument无效的参数
ENFILE*23File table overflow打开太多的文件系统
EMFILE24Too many open files打开的文件过多
EFBIG27File too large文件太大
ENOSPC28No space left on device设备上没有空间
ESPIPE29Illegal seek非法移位
EROFS30Read-only file system只读文件系统
EMLINK31Too many links太多的链接
EDOM33Math argument out of domain数值结果超出范围
ERANGE34Math result not representable数值结果不具代表性
EDEADLK35Resource deadlock would occur资源死锁错误
ENAMETOOLONG36Filename too long文件名太长
ENOLCK37No record locks available没有可用锁
ENOSYS38Function not implemented功能没有实现
ENOTEMPTY39Directory not empty目录不空
ELOOP40Too many symbolic links encountered符号链接层次太多
ENOMSG42No message of desired type没有期望类型的消息
EIDRM43Identifier removed标识符删除
ELNRNG48Link number out of range链接数超出范围
EBADR53Invalid request descriptor请求描述符无效
EBADRQC56Invalid request code无效的请求代码
ENOSTR60Device not a stream设备不是字符流
ENODATA61No data available无可用数据
ETIME62Timer expired计时器过期
EPROTO71Protocol error协议错误
EBADMSG74Not a data message非数据消息
EOVERFLOW75Value too large for defined data type值太大,对于定义数据类型
EMSGSIZE90Message too long消息太长
编程实例

demo功能:

创建一个线程并将父线程中的信息传递给子线程,在子线程中打印传递过来的信息和自身线程id值。

本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数DemoForTest。

#include <stdio.h>
#include <pthread.h>pthread_t ntid;void *ThreadFn(void *arg)
{pthread_t tid;while(1) {tid = pthread_self();printf("\n++++++++++++++  %s  %s  tid = %d ++++++++++++++\n", (char*)arg, __FUNCTION__, tid);}return ((void *)0);
}void DemoForTest()
{int err;char* str = "Hello world";err = pthread_create(&ntid, NULL, ThreadFn, (void*)str);if(err != 0) {printf("can't create thread\n");}
}

执行DemoForTest运行结果如下:

++++++++++++++  Hello world  ThreadFn  tid = 48 ++++++++++++++++++++++++++++  Hello world  ThreadFn  tid = 48 ++++++++++++++++++++++++++++  Hello world  ThreadFn  tid = 48 ++++++++++++++

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

2

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!
3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149055.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Milvus - 架构设计详解

Milvus 是一个专为在大规模密集向量数据集上进行相似性搜索而设计的开源向量数据库系统。其架构建立在流行的向量搜索库之上&#xff0c;如 Faiss、HNSW、DiskANN 和 SCANN&#xff0c;能够处理数百万、数十亿甚至数万亿的向量数据。为了全面了解 Milvus 架构&#xff0c;我们首…

R包:ggheatmap热图

加载R包 # devtools::install_github("XiaoLuo-boy/ggheatmap")library(ggheatmap) library(tidyr)数据 set.seed(123) df <- matrix(runif(225,0,10),ncol 15) colnames(df) <- paste("sample",1:15,sep "") rownames(df) <- sapp…

Temu全球下载量突破7.3亿次!Temu怎么上架产品?

拼多多旗下的出海跨境平台自2022年9月推出以来&#xff0c;在国际上的市场份额不断扩大中。最新数据显示&#xff0c;截至今年8月&#xff0c;Temu在全球的下载量已经超过了7.35亿次。这一数据充分显示了Temu在全球范围内的受欢迎程度和快速增长的势头。 具体来说&#xff0c;T…

【深度学习】03-神经网络 4-1 Dropout 正则化 - 神经网络缓解过拟合的正则化方法

参数更新&#xff0c;只是更新一部分&#xff0c;剩下的部分&#xff0c;是进行缩放。即分数会扩大。 Dropout 正则化是一种深度学习中常用的正则化技术&#xff0c;最早由 Geoffrey Hinton 等人在 2012 年提出&#xff0c;旨在防止神经网络的过拟合。 1. 来源 Dropout 是由…

【Elasticsearch系列廿二】特殊参数

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Kafka系列之:安装使用kafka_exporter详细步骤

Kafka系列之:安装使用kafka_exporter详细步骤 一、kafka_exporter二、下载kafka_exporter三、理解Topic Metrics指标四、理解Consumer Groups Metrics指标五、启动kafka_exporter六、查看页面七、systemctl托管服务一、kafka_exporter kafka_exporter源码kafka_exporter下载页…

企业智能培训新方案,高效打造金牌员工

标品市场竞争激烈&#xff0c;小微企业因长期专注于非标业务或者偏定制化路线&#xff0c;在团队专业能力与大型企业间存在显著差距。专业人才短缺、培养成本高企、培训滞后、效果难测、资源不均、考核标准不一及知识转化率低等问题&#xff0c;成为其业务转型的绊脚石。 如何高…

Java项目: 基于SpringBoot+mybatis+maven师生共评的作业管理系统(含源码+数据库+毕业论文)

一、项目简介 本项目是一套基于SpringBootmybatismaven师生共评的作业管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、…

Python办公自动化案例:实现XMind文件转换成Excel文件

案例:实现XMind文件转换成Excel文件 将XMind文件转换为Excel文件的过程可以通过几个步骤来实现,主要涉及到读取XMind文件,解析其内容,然后创建一个Excel文件并将解析的内容写入。以下是一个简化的Python脚本,展示了如何使用xmindparser库来解析XMind文件,并使用pandas库…

虚拟现实技术在相亲交友中的应用未来趋势

随着虚拟现实&#xff08;VR&#xff09;技术的不断进步&#xff0c;它已经开始渗透到我们生活的方方面面&#xff0c;其中包括相亲交友领域。相亲交友网站作为人们寻找另一半的重要平台&#xff0c;也在积极探索VR技术的应用可能性。本文将探讨VR技术在未来相亲交友网站上的几…

球体检测系统源码分享

球体检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

2024年双十一有哪些值得买?这些好物来看看!

2024年双十一有哪些值得入手的好物&#xff1f;在这个全民共享的购物盛宴里&#xff0c;我们精心挑选了一系列好物&#xff0c;旨在为您的生活添彩加温。从科技尖货到日常百货&#xff0c;从时尚潮流到家居必备&#xff0c;每一分每一秒都蕴含着超值优惠与惊喜发现。不论是自我…

无人机视角下的车辆数据集

车辆数据集 无人机视角下的车辆数据集。数据集为无人机俯拍的真实场景下的车辆机动车数据集。数据集已经标注好&#xff0c;yolo格式&#xff0c;txt标签。数据集已经划分好训练集&#xff08;20970张图片&#xff09;验证集&#xff08;5242张图片&#xff09;测试集&#xff…

峟思:山洪灾害监测预警系统全面解析

在自然灾害频发的今天&#xff0c;山洪灾害以其突发性强、破坏力大而备受关注。为了有效预防和减少山洪灾害带来的损失&#xff0c;山洪灾害监测预警系统应运而生。本文将详细介绍该系统的主要组成部分、关键传感器及其工作机制&#xff0c;以期为防灾减灾工作提供有力支持。 山…

影响RPA流程稳定运行的若干因素|实在RPA研究

RPA发展现状 当前&#xff0c;中国正处于实现高质量发展、数字化转型升级的关键时期。RPA作为数字化转型的一项重要工具&#xff0c;已经开始在许多领域发挥积极作用。 RPA&#xff08;Robotic Process Automation 机器人流程自动化&#xff09;是一种通过软件机器人自动执行…

路劲单伟彪:不乐观、不悲观,不藏着、不掖着

路劲单伟彪&#xff1a;不乐观、不悲观&#xff0c;不藏着、不掖着_简篇-美篇工作版 9月10日&#xff0c;史上超强台风“摩羯”已逐渐远离香港&#xff0c;天空开始放晴。在香港屯门凯和山&#xff0c;路劲集团主席单伟彪时隔一年再一次接受凤凰网专访。 对话自然从这一年的市场…

为什么自学python那么难?

在科技日新月异的今天&#xff0c;编程能力已成为一项备受追捧的技能。仿佛一夜之间&#xff0c;各种编程学习资源如雨后春笋般涌现&#xff0c;让人眼花缭乱。然而&#xff0c;许多人投身于自学编程的行列&#xff0c;却往往在半路折戟沉沙。究竟是什么原因让自学编程变得如此…

远程监控电脑屏幕用什么软件?8款真实好用的远程监控电脑屏幕软件推荐!

远程监控电脑屏幕是现代企业管理、远程协作以及家庭安全中的重要需求。 为了满足这一需求&#xff0c;市场上涌现出了多款功能强大、操作便捷的远程监控软件。 以下是8款真实好用的远程监控电脑屏幕软件推荐&#xff1a; 1. 安企神软件 特点&#xff1a;此软件专为企业设计&…

骨传导耳机哪个牌子好?深度解析五大高销量骨传导耳机!

在快节奏的现代生活中&#xff0c;耳机已成为我们不可或缺的伴侣&#xff0c;无论是在通勤路上、健身时还是日常工作中&#xff0c;它都能为我们提供音乐、通话和信息的即时接入。随着科技的发展&#xff0c;耳机的种类也日益丰富&#xff0c;其中骨传导耳机以其独特的声音传导…

恢复数据解决方案 :因意外删除而丢失重要数据的痛苦急救方法

您是否因意外删除 iOS 设备上的重要文件而丢失了文件&#xff1f;您听说过Geekersoft iPhone 数据恢复工具吗&#xff1f;Geekersoft iPhone 数据恢复工具提供了恢复丢失数据的完美解决方案。此 iOS 数据恢复工具具有多种恢复模式&#xff0c;可恢复已删除的文件。 全球许多用…