此规范基于业界通用的编程规范整理而成,请内核的开发人员遵守这样的编程风格。
总体原则:
在大部分情况下,开发人员应当遵从以下规范,但也有一些例外场景。如修改第三方开源代码或大量使用开源代码接口下,应当与开源代码保持一致。请依据总体原则,灵活处理。
建议按照功能模块划分子目录,子目录再定义头文件和源文件目录。
目录名和文件名如果没有特殊的需要,采用全小写的形式,可以使用下划线(“_”)分割。
推荐使用驼峰风格,具体规则如下:
类型
命名风格
形式
函数、结构体类型、枚举类型、联合体类型、typedef的类型
大驼峰,或带有模块前缀的大驼峰
AaaBbb
XXX_AaaBbb
局部变量,函数参数,宏参数,结构体中字段,联合体中成员
小驼峰
aaaBBB
全局变量
带“g_”前缀的小驼峰
g_aaaBBB
宏(不含函数式宏),枚举值,goto标签
全大写,下划线分割
AAA_BBB
函数式宏
全大写下划线分割,或大驼峰,或带有模块前缀的大驼峰
头文件防止重复的符号
以下划线“_”开头以H结尾,中间为文件名的全大写并以下划线分割
_AAA_H
内核对外API建议采用LOS_ModuleFunc的形式,如果有宾语则建议采用前置的方式,比如:
LOS_TaskCreateLOS_MuxLockkernel目录下内部模块间的接口使用OsModuleFunc的形式,比如:
OsTaskScanOsMuxInit注释一般的,尽量通过清晰的软件架构,良好的符号命名来提高代码可读性;在需要的时候,辅以注释说明。
注释是为了帮助阅读者快速读懂代码,所以要从读者的角度出发,按需注释。
注释内容要简洁、明了、无歧义,信息全面且不冗余。
注释风格要统一,建议优先选择/**/的方式,注释符与注释内容之间要有1空格,单行、多行注释风格如下:
/*单行注释*///单行注释/**多行注释*第二行*///多行注释//另一行针对代码的注释,应该置于对应代码的上方或右方。
代码上方的注释,与代码行间无空行,保持与代码一样的缩进。
代码右边的注释,与代码之间,至少留1空格。
建议将多条连续的右侧注释对齐,比如:
#defineCONST_A100/*ConstA*/#defineCONST_B2000/*ConstB*/格式程序采用缩进风格编写,使用空格而不是制表符(’\t’)进行缩进,每级缩进为4个空格。
换行时,函数左大括号另起一行放行首,并独占一行;其他左大括号跟随语句放行末。右大括号独占一行,除非后面跟着同一语句的剩余部分,如do语句中的while,或者if语句的else/elseif,或者逗号、分号。
一行只写一条语句。
比如:
structMyType{//跟随语句放行末,前置1空格...};//右大括号后面紧跟分号intFoo(inta){//函数左大括号独占一行,放行首if(a>0){Foo();//一行只有一条语句Bar();}else{//右大括号、"else"、以及后续的左大括号均在同一行...}//右大括号独占一行...}每行字符数不要超过120个,代码过长时应当换行,换行时将操作符留在行末,新行缩进一层或进行同类对齐,并将表示未结束的操作符或连接符号留在行末。
while(condition){}//Good:即使循环体是空,也应使用大括号while(condition){continue;//Good:continue表示空逻辑,使用大括号}case/default语句相对switch缩进一层,风格如下:
switch(var){case0://Good:缩进DoSomething1();//Good:缩进break;case1:{//Good:带大括号格式DoSomething2();break;}default:break;}指针类型"*"跟随变量或者函数名,例如:
int*p1;//OKint*p2;//Bad:跟随类型int*p3;//Bad:两边都没空格int*p4;//Bad:两边都有空格structFoo*CreateFoo(void);//OK:"*"跟随函数名特例:char*constVERSION="V100";//OK:当有const修饰符时,"*"两边都有空格intFoo(constchar*restrictp);//OK:当有restrict修饰符时,"*"两边都有空格sz=sizeof(int*);//OK:右侧没有变量,"*"跟随类型宏定义函数式宏前,应考虑能否用函数替代。对于可替代场景,建议用函数替代宏。对于有性能需求的场景,可以使用内联函数。
定义宏时,要使用完备的括号,例如:
#defineSUM(a,b)((a)+(b))//符合本规范要求.#defineSOME_CONST100//Good:单独的数字无需括号#defineANOTHER_CONST(-1)//Good:负数需要使用括号#defineTHE_CONSTSOME_CONST//Good:单独的标识符无需括号以下情况需要注意:
//x不要加括号#defineMAKE_STR(x)#x//obj不要加括号#defineHELLO_STR(obj)"Hello,"obj//a,b需要括号;而value可以不加括号#defineUPDATE_VALUE(value,a,b)(value=(a)+(b))//a需要括号;而b可以不加括号#defineFOO(a,b)Bar((a)+1,b)包含多条语句的函数式宏的实现语句必须放在do-while(0)中。
禁止把带副作用的表达式作为参数传递给函数式宏,比如自加操作(“a++”)。
函数式宏定义中慎用return、goto、continue、break等改变程序流程的语句。
禁止宏调用参数中出现预编译指令,如#include,#dene和#ifdef,这样做会导致未定义的行为。
宏定义不以分号结尾。
头文件应当职责单一。
避免头文件循环依赖,如a.h包含b.h,b.h包含c.h,c.h包含a.h。
头文件应当自包含,即包含某个头文件,不需要引入其他头文件就可以编译。
头文件用#dene、#ifndef、#endif保护,防止重复包含;不要使用#pragmaonce。
建议按稳定度包含头文件,依次顺序为:源码对应的头文件,C标准库,操作系统库,平台库,项目公共库,自己其他的依赖。
基础数据类型建议使用los_compiler.h中定义的类型,比如无符号32位整数位定义为UINT32。
避免大量栈分配,如较大的局部数组。
谨慎使用全局变量,尽量不用或少用全局变量。
变量应当初始化后再使用。
指向资源句柄或描述符的变量,在资源释放后立即赋予新值(如果变量的作用域马上结束可以不赋予新值)。指向资源句柄或描述符的变量包括指针、文件描述符、socket描述符以及其它指向资源的变量。
断言必须使用宏定义,且只能在调试版本中生效。
断言应当看作设计约束,禁止用断言检测程序在运行期间可能导致的错误,可能发生的错误要用错误处理代码来处理。
禁止在断言内改变运行环境。
一个断言只用于检查一个错误。
由一个进程向另一个进程发送的数据、由应用向内核发送的数据等应当进行合法性校验,校验包括但不限于:
函数应避免使用全局变量、静态局部变量和直接的I/O操作,不可避免时,应当对读写操作进行封装。
CMSIS-RTOSv2提供下面几种功能,接口详细信息可以查看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
将消息队列重置为初始空状态。(暂未实现)
静态对象分配需要访问RTOS对象控制块定义。特定于实现的头文件(下图中的os_xx.h)提供对此类控制块定义的访问。对于OpenHarmonyLiteOS-M内核,由文件名以los_开头的头文件提供,这些文件包含OpenHarmonyLiteOS-M内核的这些定义。
#include...#include"cmsis_os2.h"/*----------------------------------------------------------------------------*应用程序主线程*---------------------------------------------------------------------------*/voidapp_main(void*argument){//...for(;;){}}intmain(void){//系统初始化MySystemInit();//...osKernelInitialize();//初始化CMSIS-RTOSosThreadNew(app_main,NULL,NULL);//创建应用程序主线程osKernelStart();//开始执行线程for(;;){}}POSIX支持基本概念OpenHarmony内核使用musllibc库以及自研接口,支持部分标准POSIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。
表1process
需要包含的头文件
描述
#include
voidabort(void);
中止线程执行
#include
voidassert(scalarexpression);
断言为假终止线程
#include
intpthread_cond_destroy(pthread_cond_t*cond);
销毁条件变量
intpthread_cond_init(pthread_cond_t*restrictco
nd,constpthread_condattr_t*restrictattr);
初始化条件变量
intpthread_cond_timedwait(pthread_cond_t*restr
ictcond,pthread_mutex_t*restrictmutex,conststructtimespec*restrictabstime);
等待条件
intpthread_condattr_init(pthread_condattr_t*attr);
初始化条件变量属性对象
intpthread_mutex_unlock(pthread_mutex_t*mutex);
解锁互斥锁
intpthread_create(pthread_t*thread,constpthread_
attr_t*attr,void*(*start_routine)(void*),void*arg);
创建一个新的线程
intpthread_join(pthread_tthread,void**retval);
等待指定的线程结束
pthread_tpthread_self(void);
获取当前线程的ID
intpthread_getschedparam(pthread_tthread,int*
policy,structsched_param*param);
获取线程的调度策略和参数
intpthread_setschedparam(pthread_tthread,int
policy,conststructsched_param*param);
设置线程的调度策略和参数
intpthread_mutex_init(pthread_mutex_t*__restrictm
,constpthread_mutexattr_t*__restricta);
初始化互斥锁
intpthread_mutex_lock(pthread_mutex_t*m);
互斥锁加锁操作
intpthread_mutex_trylock(pthread_mutex_t*m);
互斥锁尝试加锁操作
intpthread_mutex_destroy(pthread_mutex_t*m);
销毁互斥锁
intpthread_attr_init(pthread_attr_t*attr);
初始化线程属性对象
intpthread_attr_destroy(pthread_attr_t*attr);
销毁线程属性对象
intpthread_attr_getstacksize(constpthread_attr
_t*attr,size_t*stacksize);
获取线程属性对象的堆栈大小
intpthread_attr_setstacksize(pthread_attr_t*attr
,size_tstacksize);
设置线程属性对象的堆栈大小
intpthread_attr_getschedparam(constpthread_
attr_t*attr,structsched_param*param);
获取线程属性对象的调度参数属性
intpthread_attr_setschedparam(pthread_attr_t*
attr,conststructsched_param*param);
设置线程属性对象的调度参数属性
intpthread_getname_np(pthread_tpthread,char
*name,size_tlen);
获取线程名称
intpthread_setname_np(pthread_tpthread,const
char*name);
设置线程名称
intpthread_cond_broadcast(pthread_cond_t*c);
解除若干已被等待条件阻塞的线程
intpthread_cond_signal(pthread_cond_t*c);
解除被阻塞的线程
intpthread_cond_wait(pthread_cond_t*__restrict
c,pthread_mutex_t*__restrictm);
表2fs
#include
char*dirname(char*path);
获取目录名
#include
structdirent*readdir(DIR*dirp);
读目录
#include
intstat(constchar*restrictpath,structstat*restrictbuf);
获取文件信息
#include
intunlink(constchar*pathname);
删除文件
#include intopen(constchar*path,intoflags,…); 用于打开文件,如文件不存在,创建文件并打开 #include intclose(intfd); 关闭文件 #include intrename(constchar*oldpath,constchar*newpath); 重命名指定的文件 DIR*opendir(constchar*dirname); 打开指定目录 intclosedir(DIR*dir); 关闭指定目录 #include intmount(constchar*source,constchar*target,con stchar*filesystemtype,unsignedlongmountflags,c onstvoid*data); 挂载文件系统 intumount(constchar*target); 卸载文件系统 intumount2(constchar*target,intflag); intfsync(intfd); 将与指定文件描述符关联的文件同步到存储设备 intmkdir(constchar*pathname,mode_tmode); 创建目录 intrmdir(constchar*path); 删除目录 intfstat(intfd,structstat*buf); 获取文件状态信息 #include intstatfs(constchar*path,structstatfs*buf); 获取指定路径下文件的文件系统信息 表3time #include intgettimeofday(structtimeval*tv,structtimezone*tz); #include structtm*gmtime(consttime_t*timep); structtm*localtime(consttime_t*timep); structtm*localtime_r(consttime_t*timep,structtm*result); time_tmktime(structtm*tm); size_tstrftime(char*s,size_tmax,constchar* format,conststructtm*tm); time_ttime(time_t*tloc); #include clock_ttimes(structtms*buf); intusleep(useconds_tusec); 休眠(微秒单位) intnanosleep(conststructtimespec*tspec1,struct timespec*tspec2); intclock_gettime(clockid_tid,structtimespec*tspec); inttimer_create(clockid_tid,structsigevent*__ restrictevp,timer_t*__restrictt); 为线程创建计时器 inttimer_delete(timer_tt); 为线程删除计时器 inttimer_settime(timer_tt,intflags,conststruct itimerspec*__restrictval,structitimerspec*__restrictold); 为线程设置计时器 time_ttime(time_t*t); char*strptime(constchar*s,constchar*format,structtm*tm); 表4util intatoi(constchar*nptr); 字符串转换整型(int) longatol(constchar*nptr); 字符串转换整型(long) longlongatoll(constchar*nptr); 字符串转换整型(longlong) #include intisalnum(intc); 检查字母数字字符 intisascii(intc); 检查ASCII intisdigit(intc); 检查数字字符 intislower(intc); 检查小写字符 intisprint(intc); 检查任何可打印字符,包括空格 intisspace(intc); 检查空格字符 intisupper(intc); 检查所传的字符是否是大写字母 intisxdigit(intc); 判断字符是否为十六进制数 longintrandom(void); 生成伪随机数 voidsrandom(unsignedintseed); 初始化随机数生成器 inttolower(intc); 字母转换成小写 inttoupper(intc); 字母转换成大写 #include typeva_arg(va_listap,type); 获取可变参数的当前参数,返回指定类型并将指针指向下一参数 voidva_copy(va_listdest,va_listsrc); 复制参数 voidva_end(va_listap); 清空va_list可变参数列表 voidva_start(va_listap,last); 定义变长参数列表的起始位置 #include char*strchr(constchar*s,intc); 在字符串中定位字符 intstrcmp(constchar*s1,constchar*s2); 比较字符串 size_tstrcspn(constchar*s,constchar*reject); 获取前缀子串的长度 char*strdup(constchar*s); 字符串拷贝到新建的位置处 size_tstrlen(constchar*s); 计算字符串长度 #include intstrncasecmp(constchar*s1,constchar*s2,size_tn); 比较固定长度字符串(忽略大小写) intstrcasecmp(constchar*s1,constchar*s2); 比较字符串(忽略大小写) intstrncmp(constchar*s1,constchar*s2,size_tn); 比较字符串(指定长度) char*strrchr(constchar*s,intc); char*strstr(constchar*haystack,constchar*needle); 寻找指定的子串 longintstrtol(constchar*nptr,char**endptr,intbase); 将字符串转换为long型整数 unsignedlongintstrtoul(constchar*nptr,char **endptr,intbase); 将字符串转换为unsignedlong型整数 unsignedlonglongintstrtoull(constchar*nptr, char**endptr,intbase); 将字符串转换为unsignedlonglong型整数 #include intregcomp(regex_t*preg,constchar*regex, intcflags); 编译正则表达式 intregexec(constregex_t*preg,constchar* string,size_tnmatch,regmatch_tpmatch[],inteflags); 匹配正则表达式 voidregfree(regex_t*preg); 释放正则表达式 char*strerror(interrnum); 返回描述错误号的字符串 表5math intabs(inti); 取绝对值 #include doublelog(doublex); 自然对数函数 doublepow(doublex,doubley); 求x的指数y次幂 doubleround(doublex); 从零开始,舍入到最接近的整数 doublesqrt(doublex); 平方根 表6IO voidclearerr(FILE*stream); 清除流的文件结尾和错误指示 intfclose(FILE*stream); 关闭文件流 FILE*fdopen(intfd,constchar*mode); 通过文件描述符打开文件流 intfeof(FILE*stream); 检测返回文件末尾指示位 intfflush(FILE*stream); 刷新流 char*fgets(char*s,intsize,FILE*stream); 读取流的下一行 intfileno(FILE*stream); 返回流的文件描述符 FILE*fopen(constchar*path,constchar*mode); 打开流 intfputs(constchar*s,FILE*stream); 向指定流写入一行 size_tfread(void*ptr,size_tsize,size_tnmemb, FILE*stream); 读一个流 intfseek(FILE*stream,longoffset,intwhence); 设置流指针的位置 longftell(FILE*stream); 获取流指针的位置 size_tfwrite(constvoid*ptr,size_tsize,size_t nmemb,FILE*stream); 向流写入 voidperror(constchar*s); 打印系统错误信息 voidrewind(FILE*stream); 重新定位流 ssize_twrite(intfd,constvoid*buf,size_tsize); 写文件内容 ssize_tread(intfd,void*buf,size_tsize); 读文件内容 表7net #include voidfreeaddrinfo(structaddrinfo*res); 释放调用getaddrinfo所分配的动态内存 intgetaddrinfo(constchar*restrictnodename,const char*restrictservname,conststructaddrinfo*restrict hints,structaddrinfo**restrictres); 网络地址和服务转换 intgetnameinfo(conststructsockaddr*restrictsa, socklen_tsalen,char*restrictnode,socklen_tnodelen ,char*restrictservice,socklen_tservicelen,intflags); 以协议无关的方式进行地址到名称的转换 #include unsignedintif_nametoindex(constchar*ifname); 通过网络接口名得到索引 #include in_addr_tinet_addr(constchar*cp); 网络主机地址点分十进制形式转换位二进制形式 char*inet_ntoa(structin_addrin); 网络主机地址二进制形式转换位点分十进制形式 constchar*inet_ntop(intaf,constvoid*src,char*dst, socklen_tsize); 网络地址转换 intinet_pton(intaf,constchar*src,void*dst); intlisten(intsockfd,intbacklog); 监听套接字 ssize_trecvmsg(intsockfd,structmsghdr*msg,intflags); 从套接字接收消息.只支持iov大小为1的场景,且不支持ancillary消息 ssize_tsend(intsockfd,constvoid*buf,size_tlen,intflags); 从socket发送消息 ssize_tsendmsg(intsockfd,conststructmsghdr*msg,intflags); 从socket发送消息。不支持ancillary消息 ssize_tsendto(intsockfd,constvoid*buf,size_tlen,int flags,conststructsockaddr*dest_addr,socklen_taddrlen); intsetsockopt(intsockfd,intlevel,intoptname,const void*optval,socklen_toptlen); 设置与套接字关联的选项 表8mem intmemcmp(constvoid*s1,constvoid*s2,size_tn); 内存比较 void*memcpy(void*dest,constvoid*src,size_tn); 内存拷贝 void*memset(void*s,intc,size_tn); 内存初始化 void*realloc(void*ptr,size_tsize); 重分配内存 void*malloc(size_tsize); 动态分配内存块大小 voidfree(void*ptr); 释放ptr所指向的内存空间 表9IPC #include intsem_timedwait(sem_t*sem,conststruct timespec*abs_timeout); 计时锁定信号量 intsem_destroy(sem_t*sem); 销毁指定的无名信号量 intsem_init(sem_t*sem,intpshared ,unsignedintvalue); 创建并初始化一个无名信号量 intsem_post(sem_t*sem); 增加信号量计数 intsem_wait(sem_t*sem); 获取信号量 #include mqd_tmq_open(constchar*mqName, intopenFlag,…); 此API用于打开一个具有指定名称的已有消息队列或创建一个新的消息队列 intmq_close(mqd_tpersonal); 此API用于关闭具有指定描述符的消息队列 intmq_unlink(constchar*mqName); 此API用于删除具有指定名称的消息队列 intmq_send(mqd_tpersonal,const char*msg,size_tmsgLen,unsignedintmsgPrio); 此API用于将具有指定内容和长度的消息放入具有指定描述符的消息队列中 ssize_tmq_receive(mqd_tpersonal,char*msg, size_tmsgLen,unsignedint*msgPrio); 此API用于从具有指定描述符的消息队列中删除最老的消息,并将其放入msg_ptr所指向的缓冲区中 intmq_timedsend(mqd_tpersonal,constchar *msg,size_tmsgLen,unsignedintmsgPrio,c onststructtimespec*absTimeout) ssize_tmq_timedreceive(mqd_tpersonal,char *msg,size_tmsgLen,unsignedint*msgPrio, conststructtimespec*absTimeout); 此API用于从具有指定描述符的消息队列消息中获取具有指定消息内容和长度的消息 intmq_setattr(mqd_tmqdes,conststructmq_ attr*__restrictnewattr,structmq_attr*__restrictoldattr); 设置描述符指定的消息队列属性 #include constchar*libc_get_version_string(void); 获取libc版本字符串 intlibc_get_version(void); 获取libc版本号 常用错误码对照表: 错误码 值 含义 ENOERR 0 Success 成功 EPERM 1 Operationnotpermitted 操作不允许 ENOENT 2 Nosuchfileordirectory 没有这样的文件或目录 ESRCH 3 Nosuchprocess 没有这样的进程(暂不支持) EINTR 4 Interruptedsystemcall 系统调用被中断 EIO 5 I/Oerror I/O错误 ENXIO 6 Nosuchdeviceoraddress 没有这样的设备或地址 E2BIG 7 Arglisttoolong 参数列表太长 ENOEXEC 8 Execformaterror 执行格式错误 EBADF 9 Badfilenumber 坏的文件描述符 ECHILD 10 Nochildprocesses 没有子进程(暂不支持) EAGAIN 11 Tryagain 资源暂时不可用 ENOMEM 12 Outofmemory 内存溢出 EACCES 13 Permissiondenied 拒绝许可 EFAULT 14 Badaddress 错误的地址 ENOTBLK 15 Blockdevicerequired 块设备请求 EBUSY 16 Deviceorresourcebusy 设备或资源忙 EEXIST 17 Fileexists 文件存在 EXDEV 18 Cross-devicelink 无效的交叉链接 ENODEV 19 Nosuchdevice 设备不存在 ENOTDIR 20 Notadirectory 不是一个目录 EISDIR 21 Isadirectory 是一个目录 EINVAL 22 Invalidargument 无效的参数 ENFILE* 23 Filetableoverflow 打开太多的文件系统 EMFILE 24 Toomanyopenfiles 打开的文件过多 EFBIG 27 Filetoolarge 文件太大 ENOSPC 28 Nospaceleftondevice 设备上没有空间 ESPIPE 29 Illegalseek 非法移位 EROFS 30 Read-onlyfilesystem 只读文件系统 EMLINK 31 Toomanylinks 太多的链接 EDOM 33 Mathargumentoutofdomain 数值结果超出范围 ERANGE 34 Mathresultnotrepresentable 数值结果不具代表性 EDEADLK 35 Resourcedeadlockwouldoccur 资源死锁错误 ENAMETOOLONG 36 Filenametoolong 文件名太长 ENOLCK 37 Norecordlocksavailable 没有可用锁 ENOSYS 38 Functionnotimplemented 功能没有实现 ENOTEMPTY 39 Directorynotempty 目录不空 ELOOP 40 Toomanysymboliclinksencountered 符号链接层次太多 ENOMSG 42 Nomessageofdesiredtype 没有期望类型的消息 EIDRM 43 Identifierremoved 标识符删除 ELNRNG 48 Linknumberoutofrange 链接数超出范围 EBADR 53 Invalidrequestdescriptor 请求描述符无效 EBADRQC 56 Invalidrequestcode 无效的请求代码 ENOSTR 60 Devicenotastream 设备不是字符流 ENODATA 61 Nodataavailable 无可用数据 ETIME 62 Timerexpired 计时器过期 EPROTO 71 Protocolerror 协议错误 74 Notadatamessage 非数据消息 EOVERFLOW 75 Valuetoolargefordefineddatatype 值太大,对于定义数据类型 EMSGSIZE 90 Messagetoolong 消息太长 demo功能: 创建一个线程并将父线程中的信息传递给子线程,在子线程中打印传递过来的信息和自身线程id值。 本演示代码在./kernel/liteos_m/testsuites/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数DemoForTest。 #include ++++++++++++++HelloworldThreadFntid=48++++++++++++++++++++++++++++HelloworldThreadFntid=48++++++++++++++++++++++++++++HelloworldThreadFntid=48++++++++++++++