1.引言
本手册从固件开发者的角度提供了NuttX实时操作系统常规的使用方法。
1.1文献综述
本用户手册分为三个部分:
* 第1部分,介绍:本节提供了一个NuttX用户手册的概要介绍。
* 第2部分,操作系统接口:本节描述了NuttX提供的程序接口的细节。这一节被分成几个段落用来描述不同的操作系统接口集:
* 第2.1段:任务控制接口
* 第2.2段:任务调度接口
* 第2.3段:任务控制接口
* 第2.4段:命名消息队列接口
* 第2.5段:计数信号量接口
* 第2.6段:时钟和计时器
* 第2.7段:信号接口
* 第2.8段:线程接口
* 第2.9段:环境变量
* 第2.10段:文件系统接口
* 第2.11段:网络接口
* 第2.12段:共享内存接口
* 第3部分,操作系统数据结构:这部分文件阐述了用于在NuttX接口中的数据结构。
* 第3.1段:标量类型
* 第3.2段:隐藏的接口手机开结构
* 第3.3段:访问errno变量
* 第3.4段:用户接口数据结构
1.2预想的受众群体
本文档的目标受众是那些希望在NuttX上面实现应用程序的固件开发人员,具体地说,该文档仅限于描述那些提供给NuttX应用程序开发者可用的实时操作系统API.因此,本文档并不关注任何关于NuttX组织或者实现的技术细节。那些技术细节将会在NuttX移植指南文档中提供。
应用程序开发人员也需要了解如何配置和构建NuttX的信息。这些信息也可以在nuttx移植指南文档中找到。
2.0操作系统接口
本节描述了在NuttX操作系统中每个可被C调用的接口。每个接口将会以如下格式被描述:
函数原型
:接口功能的C语言形式函数原型。
描述
:讨论了接口函数的相关功能。
输入参数
:所有的输入参数都会被罗列出来并且每个参数都会进行简单的描述。
返回值
:所有可能会被接口返回的返回值都会被罗列出来。以附带效果出现的返回值(通过输入的参数或变量的指针或者通过全局变量)将会在接口功能描述段落中指出。
假设/限制
:使用该接口时产生的任何不寻常的假设或者任何不明显的限制将会在这里阐述。
POSIX的兼容性
:有关于NuttX接口和其对应的POSIX接口中任何明显的不同将会在这里被指明。
注:为了实现NuttX接口函数名字空间的独立,函数名称和类型的差异是被希望的,并且在这些段落中不会被认为是不同而加以区分。
2.1任务控制接口
任务:NuttX是一个平面地址的操作系统。因此,它不支持像Linux那样的进程(地址空间)。XuttX是只支持运行在同一地址空间的简单的线程。然而,编程模型在任务和线程之间做了一些区别:
* 任务是具有一定的独立性的线程组。
* 线程间可以共享一些资源。
文件描述符和流:这尤其适用于打开的文件描述符和流的情况下。当使用本节中的接口启动一个任务时,那么最多将创建三个打开的文件。
如果CONFIG_DEV_CONSOLE被定义,前三个文件描述符(对应stdin,stdout和stderr)将会被复制到新任务。由于这些文件描述符是重复的,子任务可以自由地关闭它们或以任何方式操作它们而不会影响父任务。任务中的与文件相关的操作(打开、关闭等)将不会对其他任务产生影响。由于这三个文件描述符是重复的,也可以实现某种程度上的重定向.
线程,从另一方面来说,通常会与父线程共享文件描述符。在这种情况下,文件操作将会影响到来自于同一父线程的所有子线程。
在文件系统中执行程序:NuttX也会提供单独的接口用以执行驻留在文件系统中独立编译的程序。这些内部接口然而并不是标准的并且他们将会在《NuttX binary loader》和《NXFLAT》两篇文档中被描述。
-
任务控制接口.以下是由NuttX提供任务控制接口:
-
由VxWorks接口引入的非标准任务控制接口:
2.1.1 task_create
2.1.2 task_init
2.1.3 task_activate
2.1.4 task_delete
2.1.5 task_restart -
类似于VxWorks的非标准扩展接口,用以支持POSIX的线程取消点特性。
2.1.6 task_setcancelstate
2.1.7 task_setcanceltype
2.1.8 task_testcancel -
标准接口
2.1.9退出
2.1.10 getpid -
标准vfork和exec [v|l]接口:
2.1.11 vfork
2.1.12 execv
2.1.13 EXECL -
标准的posix_spawn接口:
2.1.14 posix_spawn_abd_posix_spawnp
2.1.15 posix_spawn_file_actions_init
2.1.16 posix_spawn_file_actions_destroy
2.1.17 posix_spawn_file_actions_addclose
2.6.18 posix_spawn_file_actions_adddup2
2.1.19 posix_spawn_file_actions_addopen
2.1.20 posix_spawnattr_init
2.1.21 posix_spawnattr_getflags
2.1.22 posix_spawnattr_getschedparam
2.1.23 posix_spawnattr_getschedpolicy
2.1.24 posix_spawnattr_getsigmask
2.1.25 posix_spawnattr_setflags
2.1.26 posix_spawnattr_setschedparam
2.1.27 posix_spawnattr_setschedpolicy
2.1.28 posix_spawnattr_setsigmask -
灵感来自与posix_spawn的非标准任务控制接口:
2.1.29 task_spawn
2.1.30 task_spawnattr_getstacksize
2.1.31 task_spawnattr_setstacksize
2.1.32 posix_spawn_file_actions_init
-
-
2.1.1 task_create
函数原型
:
#include <sched.h>
int task_create(char *name, int priority, int stack_size, main_t entry, char * const argv[]);
描述
:此函数根据指定的优先级创建和激活一个新任务并返回系统分配的ID。
入口地址是任务的“主”函数的地址。一旦设置了C环境,这个函数将被调用。该函数被调用时将传入四个参数。当制定的过程返回时(也就是main函数返回时),exit()将会被自动调用。
注意,任意数量的参数都可以传递给相关的函数。
传入参数将会被复制(通过strdup)使传入的参数的生命周期并不依赖于调用task_create()的父函数。
新创建的任务不从父任务继承调度器的特征:新任务开始时,将开始于系统默认的优先级和SCHED_FIFO调度策略。这些特征可以在新的任务开始后修改。
新创建的任务将会继承前三个文件描述符(对应stdin,stdout和stderr,)和标准I/O重定向的支持。
输入参数
:
name. 新任务的名字
priority. 新任务的优先级
stack_size. 新任务需要的栈空间大小(以字节计)
entry. 新任务的入口点
argv. 输入参数数组的指针,最多可以提供CONFIG_MAX_TASK_ARG个,如果少于CONFIG_MAX_TASK_ARG个参数被传入,那么参数列表将需要以空值作为结尾,如果不需要参数,那么argv将会是NULL。
返回值
:返回新的任务非零的任务ID或者如果内存不足或任务不能创造的时候将会返回ERROR(没有设置errno)。
假设/限制
:
POSIX的兼容性
:这是一个非POSIX接口,VxWroks提供如下类似的接口:
int taskSpawn(char *name, int priority, int options, int stackSize, FUNCPTR entryPt,int arg1, int arg2, int arg3, int arg4, int arg5,int arg6, int arg7, int arg8, int arg9, int arg10);
NuttX的task_create()与VxWorks的taskSpawn()有着如下的不同:- 接口名字
- 不同类型的参数
- 没有可选参数(NuttX中)
-
可变个数的参数可以被传递给一个task(对应VxWorks最多支持10个)
-
2.1.2 task_init
函数原型
:
#include <sched.h>
int task_init(struct tcb_s *tcb, char *name, int priority, uint32_t *stack, uint32_t stack_size,maint_t entry, char * const argv[]);
描述
:此函数初始化一个进程控制块(TCB)用以启动一个新的线程。它扮演着task_create()功能的子集。但是不像是task_create(),task_init()不会激活该线程,该创建的线程必须通过调用task_activate()去激活。
输入参数
:
tcb. 新任务的进程控制块的地址
name. 新任务的名字 (未被使用)
priority. 新任务的优先级
stack. 预先分配的栈的起始地址
stack_size. 预先分配的栈的大小(以字节计)
entry. 新任务的入口点
argv. 输入参数数组的指针,最多可以提供CONFIG_MAX_TASK_ARG个,如果少于CONFIG_MAX_TASK_ARG个参数被传入,那么参数列表将需要以空值作为结尾,如果不需要参数,那么argv将会是NULL。
返回值
:返回OK,如果任务没被初始化那么返回ERROR。
新的任务仅当无法设置一个新的唯一的任务ID给任务控制块时会失败(没有设置errno)。
假设/限制
:taks_init()提供给操作系统内部支持。不建议用作常规的使用。task_create()才是首选的用于初始化并且启动一个任务的接口。
POSIX的兼容性
:这是一个非POSIX接口,VxWroks提供如下类似的接口:
STATUS taskInit(WIND_TCB *pTcb, char *name, int priority, int options, uint32_t *pStackBase, int stackSize,FUNCPTR entryPt, int arg1, int arg2, int arg3, int arg4, int arg5,int arg6, int arg7, int arg8, int arg9, int arg10);
NuttX的task_init()与VxWorks的taskInit()有着如下的不同:- 接口名字
- 不同类型的参数
- 没有可选参数(NuttX中)
-
可变个数的参数可以被传递给一个task(对应VxWorks最多支持10个)
-
2.1.3 task_activate
函数原型
#include <sched.h>
int task_activate(struct tcb_s *tcb);
描述
:此函数激活由task_init()创建的任务。没有激活的任务是没有资格被调度器执行的。
输入参数
:
tcb. 新任务的进程控制块的地址。
返回值
:返回OK,如果任务不能被激活的话那么返回ERROR(没有设置errno)。
假设/限制
:taks_activate()提供给操作系统内部支持。不建议用作常规的使用。task_create()才是首选的用于初始化并且启动一个任务的接口。
POSIX的兼容性
:这是一个非POSIX接口,VxWroks提供如下类似的接口:
STATUS taskActivate(int tid);
NuttX的task_activate()与VxWorks的taskActivate()有着如下的不同:- 接口名字
-
在VxWorks的taskActivate函数中,pid参数是WIND_TCB指针转换成整形的值(也就是该tid实际上是TCB的地址映射。由于内存地址唯一,所以也可保证tid在系统中唯一)
-
2.1.4 task_delete
函数原型
#include <sched.h>
int task_delete(pid_t pid);
描述
:此函数将取消指定任务的运行。其栈和进程控制块将会被释放。函数与task_create()相对应。这是暴露给用户的版本;它起始是内部函数task_terminate()的一个封装。
输入参数
:
pid.将要删除的任务控制块ID。ID为0表明调用该函数的任务。调用该函数的任务的任何尝试将会被自动重定向到exit().
返回值
:返回OK,如果任务不能被删除的话那么返回ERROR。errno将会被设置用以指明错误的行为。该函数可以失败,例如,提供的pid并不对应正在执行的一个任务。
假设/限制
:taks_delete()必须被小心地使用。如果任务持有资源(例如已分配的内存或者被其他任务需要的信号量),task_delete()可能会导致这些资源的错乱。
POSIX的兼容性
:这是一个非POSIX接口,VxWroks提供如下类似的接口:
STATUS taskDelete(int tid);
NuttX的task_activate()与VxWorks的taskActivate()有着如下的不同:- 系统不支持任务删除例程(因为系统不支持VxWroks的taskDeleteHookAdd()函数)。然而,如果atexit()或者on_exit()支持被使能的话,当任务删除时,他们将会被调用。
-
删除自身是被支持的,但是这种情况下,task_delete()对自身进程的删除调用将会重定向到exit()函数上。
-
2.1.3 task_activate
函数原型
#include <sched.h>
int task_activate(struct tcb_s *tcb);
描述
:此函数激活由task_init()创建的任务。没有激活的任务是没有资格被调度器执行的。
输入参数
:
tcb. 新任务的进程控制块的地址。
返回值
:返回OK,如果任务不能被激活的话那么返回ERROR(没有设置errno)。
假设/限制
:taks_activate()提供给操作系统内部支持。不建议用作常规的使用。task_create()才是首选的用于初始化并且启动一个任务的接口。
POSIX的兼容性
:这是一个非POSIX接口,VxWroks提供如下类似的接口:
STATUS taskActivate(int tid);
NuttX的task_activate()与VxWorks的taskActivate()有着如下的不同:- 接口名字
-
在VxWorks的taskActivate函数中,pid参数是WIND_TCB指针转换成整形的值(也就是该tid实际上是TCB的地址映射。由于内存地址唯一,所以也可保证tid在系统中唯一)
-
2.1.4 task_delete
函数原型
#include <sched.h>
int task_delete(pid_t pid);
描述
:此函数将取消指定任务的运行。其栈和进程控制块将会被释放。函数与task_create()相对应。这是暴露给用户的版本;它起始是内部函数task_terminate()的一个封装。
输入参数
:
pid.将要删除的任务控制块ID。ID为0表明调用该函数的任务。调用该函数的任务的任何尝试将会被自动重定向到exit().
返回值
:返回OK,如果任务不能被删除的话那么返回ERROR。errno将会被设置用以指明错误的行为。该函数可以失败,例如,提供的pid并不对应正在执行的一个任务。
假设/限制
:taks_delete()必须被小心地使用。如果任务持有资源(例如已分配的内存或者被其他任务需要的信号量),task_delete()可能会导致这些资源的错乱。
POSIX的兼容性
:这是一个非POSIX接口,VxWroks提供如下类似的接口:
STATUS taskDelete(int tid);
NuttX的task_activate()与VxWorks的taskActivate()有着如下的不同:- 系统不支持任务删除例程(因为系统不支持VxWroks的taskDeleteHookAdd()函数)。然而,如果atexit()或者on_exit()支持被使能的话,当任务删除时,他们将会被调用。
-
删除自身是被支持的,但是这种情况下,task_delete()对自身进程的删除调用将会重定向到exit()函数上。
-
2.1.5 task_restart
函数原型
#include <sched.h>
int task_restart(pid_t pid);
描述
:此函数”重启”一个任务。任务首先被停止然后以与其第一次启动一样的优先级,同样ID,原始的入口点,栈大小,参数等重新初始化。
注意
:- 常规的任务退出时相关的清除操作不会被执行。例如,文件描述符不会被关闭;任何之前打开的文件将会在任务重新初始化后继续保持打开状态。
- 任务重启之前申请的内存在任务重启后将不会被释放。所以一个强制需要可重启的任务必须被以一种可避免内存泄露的方式设计。
-
初始化数据不会被重置。全局或者静态的变量会保持在任务停止前的状态。这个特性可以被重启进程用来检测其是否已经被重启。
输入参数
:
pid. 希望重启的任务的ID,ID为0指明的是当前调用该函数的任务(尽管,对任务重启自身的支持还还没有实现)。
返回值
:返回OK,如果任务不能被重启的话那么返回ERROR。函数在如下条件下可能失败:
- 0或主调用函数的pid被传入给了task_restart()(功能未实现)
-
pid并不关联于当前系统中任何的任务(没有哪个任务对应这个pid)。
假设/限制
:
POSIX的兼容性
:这是一个非POSIX接口,VxWroks提供如下类似的接口:
STATUS taskRestart(int tid);
NuttX的task_restart()与VxWorks的taskRestart()有着如下的不同:
- NuttX上并不支持重启当前正在执行的任务(然而VxWorks是支持的)
-
在VxWorks描述说系统会接管任务终止时的ID,优先级等等。
-
2.1.6 task_setcancelstate
函数原型
#include <sched.h>
int task_setcancelstate(int state, int *oldstate);
描述
:此函数自动设定当前调用任务的可撤销状态(state)并且返回任务之前的可撤销状态(oldstate)合法的值状态是TASK_CANCEL_ENABLE和TASK_CANCEL_DISABLE。
任何挂起的线程,当线程可撤销状态设置为TASK_CANCEL_ENABLE时,都可能会被撤销。
任何新创建的任务的取消状态的类型,可能是TASK_CANCEL_ENABLE或TASK_CANCEL_DISABLE。
输入参数
:
state. 新的可撤销状态. TASK_CANCEL_ENABLE或TASK_CANCEL_DISABLE两者选其一.
oldstate. 定位老的可撤销状态.
返回值
:成功返回OK或0,如果失败的话那么返回ERROR。errno将会被恰当的设置用以指明错误的行为。
假设/限制
:
POSIX的兼容性
:这是一个非标准接口,它扩展了pthread_setcancelstate()功能针对任务的版本,并且支持使用task_delete()。
-
2.1.7 task_setcanceltype
函数原型
#include <sched.h>
int task_setcanceltype(int type, FAR int *oldtype);
描述
:此函数自动设定当前调用任务的可撤销类型(type)并且返回任务之前的可撤销类型(oldtype)合法的值状态是TASK_CANCEL_DEFERRED和TASK_CANCEL_ASYNCHRONOUS。
任何新创建的任务可撤销状态和类型,分别将是TASK_CANCEL_ENABLE和TASK_CANCEL_DEFERRED。
输入参数
:
type. 新的可撤销类型. TASK_CANCEL_DEFERRED或TASK_CANCEL_ASYNCHRONOUS两者选其一.
oldTYPE. 定位老的可撤销类型.。
返回值
:成功返回OK或0,如果失败的话那么返回ERROR。errno将会被恰当的设置用以指明错误的行为。
假设/限制
:
POSIX的兼容性
:这是一个非标准接口,它扩展了pthread_setcanceltype()功能针对任务的版本,并且支持使用task_delete()。
-
2.1.8 task_testcancel
函数原型
#include <sched.h>
int task_testcancel(void);
描述
:此函数在调用任务中创建一个进程取消点。如果任务可撤销状态是禁止的话,那么该函数没有作用。
输入参数
:
返回值
:
假设/限制
:
POSIX的兼容性
:这是一个非标准接口,它扩展了pthread_testcancel()功能针对任务的版本,并且支持使用task_delete()。
-
2.1.9 exit
函数原型
` #include