管道:介绍和基本服务

Pipes introduction and basic services

与邮箱或队列相比,它们提供了在任务之间传递简单消息的更灵活的方式。

使用管道

在Nucleus SE中,管道是在构建时配置的。一个应用程序最多可以配置16个管道。如果未配置管道,则应用程序中不会包含与管道相关的数据结构或服务调用代码。

管道仅仅是一组存储位置,每个存储位置都足够大,足以容纳一个用户定义字节长度的数据项,对这些数据项的访问是受控制的,以便可以由多个任务安全地使用它。任务可以重复写入管道,直到所有位置都已满。任务可以从管道中读取,数据通常以先进先出(FIFO)的方式接收。尝试发送到完整管道或从空管道读取可能会导致错误或任务挂起,具体取决于在API调用和Nucleus SE配置中选择的选项。

管道和队列

Nucleus SE还支持队列,管道和队列之间的主要区别是消息大小。队列携带由单个ADDR组成的消息,这些地址通常是指针。管道承载任意字节长的消息;应用程序中每个管道的大小是固定的,并在配置时设置。

配置管道

管道数量

与Nucleus SE的大多数方面一样,管道的配置主要由nuse_config.h中的#define语句控制。键设置是NUSE_PIPE_NUMBER,它确定为应用程序配置了多少个管道。默认设置为0(即没有管道正在使用),您可以将其设置为最大16的任何值。错误的值将导致编译时错误,该错误由nuse_config_check.h中的测试生成(此错误包含在nuse_config.c中,因此使用此模块进行编译),从而导致编译一个#错误语句。

选择非零值是管道的“主启用”。这将导致一些数据结构被相应地定义和调整大小,在下一篇文章中会有更多内容。它还激活API启用设置。

API启用

Nucleus SE中的每个API函数(服务调用)在nuse_config.h中都有一个启用的#define符号。对于管道,包括:

NUSE_PIPE_SEND

NUSE_PIPE_RECEIVE

NUSE_PIPE_JAM

NUSE_PIPE_RESET

NUSE_PIPE_INFORMATION

NUSE_PIPE_COUNT

默认情况下,所有这些都设置为FALSE,从而禁用每个服务调用并禁止包含任何实现代码。要为应用程序配置管道,需要选择要使用的API调用,并将其启用符号设置为TRUE。
下面是从默认nuse_config.h文件中提取的内容。

#define NUSE_PIPE_NUMBER 0 /* Number of pipes in the

system – 0-16 */

/* Service call enablers */

#define
NUSE_PIPE_SEND FALSE

#define
NUSE_PIPE_RECEIVE FALSE

#define
NUSE_PIPE_JAM FALSE

#define
NUSE_PIPE_RESET FALSE

#define
NUSE_PIPE_INFORMATION FALSE

#define
NUSE_PIPE_COUNT FALSE

如果启用了管道API函数而未配置管道(除非始终允许使用NUSE_pipe_Count()),则会导致编译时错误。如果您的代码使用尚未启用的API调用,则会导致链接时间错误,因为应用程序中不会包含任何实现代码。

管道服务电话

Nucleus RTOS支持10个与管道相关的服务调用,它们提供以下功能:

向管道发送消息。由Nucleus SE中的NUSE_Pipe_Send()实现。

从管道接收消息。由Nucleus SE中的NUSE_Pipe_Receive()实现。

在管道前面发个信息。由Nucleus SE中的NUSE_Pipe_Jam()实现。

将管道恢复到未使用状态,不暂停任何任务(重置)。由Nucleus SE中的NUSE_Pipe_Reset()实现。

提供有关指定管道的信息。由Nucleus SE中的NUSE_Pipe_Information()实现。

返回(当前)为应用程序配置的管道数的计数。由Nucleus SE中的NUSE_Pipe_Count()实现。

向应用程序添加新管道(创建)。未在Nucleus SE中实现。

从应用程序中删除管道(删除)。未在Nucleus SE中实现。

返回指向应用程序中所有管道(当前)的指针。未在Nucleus SE中实现。

向管道(广播)上挂起的所有任务发送消息。未在Nucleus SE中实现。

将详细检查每个服务调用的实现。

管道读写服务

可以在管道上执行的基本操作是向管道写入数据(有时称为发送)和从中读取数据(也称为接收)。也可以将数据写入管道前端,这也被称为堵塞。Nucleus RTOS和Nucleus SE各自为这些操作提供了三个基本API调用,这里将对此进行讨论。

写在管道上

Nucleus RTOS API对管道的写入调用非常灵活,允许您无限期地挂起,或者在操作无法立即完成的情况下暂停,也就是说,您尝试写入一个完整的管道。Nucleus SE提供相同的服务,除了task suspend是可选的并且不实现timeout。

Nucleus RTOS还提供了一个向管道广播的功能,但Nucleus
SE不支持这种功能。

Nucleus RTOS API Call for Sending to a Pipe

Service call prototype:

STATUS NU_Send_To_Pipe(NU_PIPE *pipe, VOID *message,

UNSIGNED size, UNSIGNED suspend);

Parameters:

pipe – pointer to the user-supplied pipe control block

message – a pointer to the message to be sent

size – the number of bytes in the message. If the pipe supports variable-length messages, this parameter must be equal to or less than the message size supported by the pipe. If the pipe supports fixed-size messages, this parameter must be exactly the same as the message size supported by the pipe

suspend – specification for task suspend; may be NU_NO_SUSPEND or NU_SUSPEND or a timeout value

Returns:

NU_SUCCESS – the call was completed successfully

NU_INVALID_PIPE – the pipe pointer is invalid

NU_INVALID_POINTER – the message pointer is NULL

NU_INVALID_SIZE – the message size is incompatible with the message size supported by the pipe

NU_INVALID_SUSPEND – suspend was attempted from a non-task thread

NU_PIPEE_FULL – the pipe is full and suspend was not specified

NU_TIMEOUT – the pipe is still full even after suspending for the specified timeout value

NU_PIPE_DELETED – the pipe was deleted while the task was suspended

NU_PIPE_RESET – the pipe was reset while the task was suspended

Nucleus SE API Call for Sending to a Pipe

This API call supports the key functionality of the Nucleus RTOS API.

Service call prototype:

<="" font="" style=“box-sizing: inherit;”>

<="" font="" style=“box-sizing: inherit;”>

STATUS NUSE_Pipe_Send(NUSE_PIPE pipe, U8 *message,

U8 suspend);

Parameters:

pipe – the index (ID) of the pipe to be utilized

message – a pointer to the message to be sent, which is a sequence of bytes as long as the configured message size of the pipe

suspend – specification for task suspend; may be NUSE_NO_SUSPEND or NUSE_SUSPEND

Returns:

NUSE_SUCCESS – the call was completed successfully

NUSE_INVALID_PIPE – the pipe index is invalid

NUSE_INVALID_POINTER – the message pointer is NULL

NUSE_INVALID_SUSPEND – suspend was attempted from a non-task
thread or when blocking API calls were not enabled

NUSE_PIPE_FULL – the pipe is full and suspend was not specified

NUSE_PIPE_WAS_RESET – the pipe was reset while the task was
suspended

管道发送的核SE实现

NUSE_Pipe_Send()–检查API函数是否已启用suspend()的条件编译(取决于u)的API是否已启用。我们将在这里分别研究这两种变体。

如果未启用阻塞,则此API调用的代码非常简单:

if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full /{ return_value = NUSE_PIPE_FULL;}else / pipe element available */{ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS;}

该函数只检查管道中是否有空间,并使用NUSE_pipe_Head[]索引将消息存储在管道的数据区域中。

启用阻塞后,代码会变得更复杂:

do{ if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full / { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_FULL; } else { / block task / NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else / pipe element available */ { data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; / check whether a task is blocked on this pipe */ NUSE_Pipe_Blocking_Count[pipe]–; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; }} while (suspend == NUSE_SUSPEND);

对代码的一些解释可能有用:

代码包含在do…while循环中,当参数suspend的值为NUSE_suspend时,循环将继续。

如果管道已满,并且suspend设置为NUSE_NO_suspend,则API调用将以NUSE_pipe_full退出。如果suspend设置为NUSE_suspend,则任务将被挂起。返回时(即,当任务被唤醒时),如果返回值为NUSE_SUCCESS,表示任务被唤醒是因为消息已被读取(而不是重置管道),则代码循环返回顶部。

如果管道未满,则使用NUSE_pipe_Head[]索引存储提供的消息,以将消息存储在管道的数据区域中。检查管道上是否有任何任务挂起(等待接收)。如果有任务等待,第一个任务被唤醒。suspend变量被设置为NUSE_NO_suspend,API调用将退出并返回NUSE_SUCCESS。

从管子里读东西

从管道读取的Nucleus RTOS API调用非常灵活,使您能够无限期地挂起,或者在操作无法立即完成的情况下暂停,也就是说,您尝试从空管道中读取。Nucleus SE提供相同的服务,除了task suspend是可选的并且不实现timeout。

ucleus RTOS API Call for Receiving from a Pipe

Service call prototype:

STATUS NU_Receive_From_Pipe(NU_PIPE *pipe, VOID *message, UNSIGNED size, UNSIGNED *actual_size, UNSIGNED suspend);

Parameters:

pipe – pointer to user-supplied pipe control block

message – pointer to storage for the message to be received

size –
the number of bytes in the message. This number must correspond to the message size defined when the pipe was created

suspend – specification for task suspend; may be NU_NO_SUSPEND or NU_SUSPEND or a timeout value

Returns:

NU_SUCCESS – the call was completed successfully

NU_INVALID_PIPE – the pipe pointer is invalid

NU_INVALID_POINTER – the message pointer is NULL

NU_INVALID_SUSPEND – suspend was attempted from a non-task

NU_PIPE_EMPTY – the pipe is empty and suspend was not specified

NU_TIMEOUT – indicates that the pipe is still empty even after suspending for the specified timeout value

NU_PIPE_DELETED –
the pipe was deleted while the task was suspended

NU_PIPE_RESET – the pipe was reset while the task was suspended

Nucleus SE API Call for Receiving from a Pipe

This API call supports the key functionality of the Nucleus RTOS API.

Service call prototype:

STATUS NUSE_Pipe_Receive(NUSE_PIPE pipe, U8 *message,

U8 suspend);

Parameters:

pipe – the index (ID) of the pipe to be utilized

message – a pointer to storage for the message to be received, which is a sequence of bytes as long as the configured message size of the pipe

suspend – specification for task suspend; may be NUSE_NO_SUSPEND or NUSE_SUSPEND

Returns:

NUSE_SUCCESS – the call was completed successfully

NUSE_INVALID_PIPE – the pipe index is invalid

NUSE_INVALID_POINTER – the message pointer is NULL

NUSE_INVALID_SUSPEND – suspend was attempted from a non-task thread or when blocking API calls were not enabled

NUSE_PIPE_EMPTY – the pipe is empty and suspend was not specified

NUSE_PIPE_WAS_RESET – the pipe was reset while the task was suspended

Nucleus SE Implementation of Pipe Receive

管道接收的核SE实现

NUSE_Pipe_Receive()API函数的大部分代码(在参数检查之后)是通过条件编译选择的,这取决于是否启用了对阻塞(任务挂起)API调用的支持。我们将在这里分别研究这两种变体。

如果未启用阻塞,则此API调用的代码非常简单:

if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty /{ return_value = NUSE_PIPE_EMPTY;}else{ / message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = *data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]–; *actual_size = msgsize; return_value = NUSE_SUCCESS;}

只需使用管道中的指针NUSE_Pipe_Tail[]从数据管道中返回数据,并通过管道返回数据。 启用阻塞后,代码会变得更复杂:

do{ if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty / { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_EMPTY; } else { / block task / NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else { / message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]–; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; / check whether a task is blocked / / on this pipe */ NUSE_Pipe_Blocking_Count[pipe]–; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } *actual_size = msgsize; return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; }} while (suspend == NUSE_SUSPEND);

对代码的一些解释可能有用:

代码包含在do…while循环中,当参数suspend的值为NUSE_suspend时,循环将继续。

如果管道为空,并且suspend设置为NUSE_NO_suspend,则API调用将以NUSE_pipe_empty退出。如果suspend设置为NUSE_suspend,则任务将被挂起。返回时(即,当任务被唤醒时),如果返回值为NUSE_SUCCESS,表示任务因已发送消息而被唤醒(而不是重置管道),则代码循环返回顶部。

如果管道包含任何消息,则使用NUSE_pipe_Tail[]索引返回存储的消息,以从管道的数据区域获取消息。检查管道上是否有任何任务被挂起(等待发送)。如果有任务等待,第一个任务被唤醒。suspend变量被设置为NUSE_NO_suspend,API调用将退出并返回NUSE_SUCCESS。

写在管道前面

Nucleus RTOS-API调用写入管道的前端非常灵活,允许您无限期地挂起,或者在操作无法立即完成的情况下暂停超时;也就是说,您尝试写入一个完整的管道。Nucleus SE提供相同的服务,除了task suspend是可选的并且不实现timeout。

Nucleus RTOS API Call for Jamming to a Pipe

Service call prototype:

STATUS NU_Send_To_Front_Of_Pipe(NU_PIPE *pipe, VOID *message,

UNSIGNED size, UNSIGNED suspend);

Parameters:

pipe – pointer to a user-supplied pipe control block

message – a pointer to the message to be sent

size – the number of bytes in the message. If the pipe supports variable-length messages, this parameter must be equal to or less than the message size supported by the pipe. If the pipe supports fixed-size messages, this parameter must be exactly the same as the message size supported by the pipe.

suspend – specification for task suspend; may be NU_NO_SUSPEND or NU_SUSPEND or a timeout value

Returns:

NU_SUCCESS – the call was completed successfully

NU_INVALID_PIPE – the pipe pointer is invalid

NU_INVALID_POINTER – the message pointer is NULL

NU_INVALID_SIZE – the message size is incompatible with the message size supported by the pipe

NU_INVALID_SUSPEND – suspend was attempted from a non-task thread

NU_PIPE_FULL – the pipe is full and suspend was not specified

NU_TIMEOUT – the pipe is still full even after suspending for the specified timeout value

NU_PIPE_DELETED – the pipe was deleted while the task was suspended

NU_PIPE_RESET – the pipe was reset while the task was suspended

Nucleus SE API Call for Jamming to a Pipe

This API call supports the key functionality of the Nucleus RTOS API.

Service call prototype:

STATUS NUSE_Pipe_Jam(NUSE_PIPE pipe, ADDR *message,

U8 suspend);

Parameters:

pipe – the index (ID) of the pipe to be utilized

message – a pointer to the message to be sent, which is a sequence of bytes as long as the configured message size of the pipe

suspend – specification for task suspend; may be NUSE_NO_SUSPEND or NUSE_SUSPEND

Returns:

NUSE_SUCCESS – the call was completed successfully

NUSE_INVALID_PIPE – the pipe index is invalid

NUSE_INVALID_POINTER – the message pointer is NULL

NUSE_INVALID_SUSPEND – suspend was attempted from a non-task thread or when blocking API calls were not enabled

NUSE_PIPE_FULL – the pipe is full and suspend was not specified

NUSE_PIPE_WAS_RESET – the pipe was reset while the task was suspended

Nucleus SE Implementation of Jamming to a Pipe

The bulk of the code of the NUSE_Pipe_Jam() API function is very similar to that of NUSE_Pipe_Send() , except that the data is stored using the NUSE_Pipe_Tail[] index,
thus:

if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full /{ return_value = NUSE_PIPE_FULL;}else / pipe element available */{ if (NUSE_Pipe_Tail[pipe] == 0) { NUSE_Pipe_Tail[pipe] = (NUSE_Pipe_Size[pipe] - 1) * msgsize; } else { NUSE_Pipe_Tail[pipe] -= msgsize; } data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS;}

管道:介绍和基本服务相关推荐

  1. Oracle11g服务详细介绍及哪些服务是必须开启的?

    Oracle11g服务详细介绍及哪些服务是必须开启的? Oracle ORCL VSS Writer Service Oracle卷映射拷贝写入服务,VSS(Volume Shadow Copy Se ...

  2. coverity代码检测工具介绍_微服务测试之静态代码扫描

    静态代码扫描为整个发展组织增加价值.无论您在开发组织中发挥的作用如何,静态代码扫描解决方案都具有附加价值,拥有软件开发中所需要的尖端功能,最大限度地提高质量并管理软件产品中的风险. 背景 微服务架构模 ...

  3. android 各种服务介绍,Android 网络服务介绍

    1. 介绍 Android网络服务主要包括如下四个部分 -ConnectivityService: 提供数据连接管理服务,包括移动数据.WIFI.以太网等-NetworkPolicyManagerSe ...

  4. NFS介绍、NFS服务端配置安装配置、 NFS配置选项、 客户端的配置

    NFS介绍 NFS是Network File System的缩写 ,是在网络层面,NFS(Network File System)网络文件系统会经常用到,用于在网络上共享存储.这样讲,你对NFS可能不 ...

  5. OAuth2.0_环境介绍_授权服务和资源服务_Spring Security OAuth2.0认证授权---springcloud工作笔记138

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 环境介绍 1.可以看到客户端首先访问/oauth/token 这个路径来请求令牌,这个接口是spr ...

  6. NFS介绍,NFS服务端安装配置,NFS配置选项

    2019独角兽企业重金招聘Python工程师标准>>> NFS介绍: NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网 ...

  7. NFS(NFS介绍,NFS服务端和客户端配置)

    一.NFS服务介绍 NFS是 Network File system的缩写 分为2.3.4三个版本,2和3由sun公司起草开发,4.0开始netapp公司参与并主导开发 NFS数据传输基于RPC协议:

  8. (14)UVM 史上最全通信管道介绍

    UVM通信管道 文章目录 UVM通信管道 一.前言 二.TLM FIFO 三.Analysis Port 四.Analysis TLM FIFO 五.Request & Response 通信 ...

  9. webService(二) 几种常用的框架介绍及Axis 服务端搭建。

    一.框架介绍 1.Apache CXF 是由XFire和 Celtix 两个现有的项目进行了重组而形成的新框架,能够与spring完美衔接.支持WS-Addressing.WS-Policy.WS-R ...

最新文章

  1. python后端开发工程师做什么-如何面试Python后端工程师?
  2. LeaFlet学习之GridLayer扩展
  3. CygWin / 安装软件包的方法
  4. 用内卷搞垮团队!您可真行
  5. 技术MBA高科技企业的“宠儿”
  6. BZOJ2654:tree(最小生成树,二分)
  7. 转:过度疲劳的27个信号与预防方法
  8. freeradius+mysql+pptpd+radiusmanager 游戏×××代理站完整实验过程
  9. perl删除Windows下的图片缓存缩略图(Thumbs.db)
  10. 使用nssm注册系统服务的详细方法
  11. 随缘刷题算法学习笔记
  12. wp下载吧主题模板_内含newzhan2.60无授权版本
  13. Cors跨域(二):实现跨域Cookie共享的三要素
  14. 这猪蹄是人类能吃完的?
  15. Hbuilder 真机运行显示未受信任的解决方法(ios)
  16. 电脑python如何下载_Python for Windows 32位 v3.7.2下载|Python 3.7.2免费电脑版
  17. 公司AppleID的申请详细流程
  18. Mysql聚集索引和非聚集索引(堆组织表和索引组织表)
  19. 系统无法在消息文件中为 Application 找到消息号为 0x2350 的消息文本。
  20. 【FXCG】对市场保持敬畏之心

热门文章

  1. 程序主动进行电话短信报警,自定义电话、短信、钉钉报警通知
  2. jar包升级部署到服务器详细流程,将服务部署在linux中
  3. python程序如何执行死刑图片_如何判断对象已死
  4. 关于C语言中的数组指针、指针数组以及二级指针
  5. 微机原理—定时计数控制接口
  6. NLP自然语言处理工具小结
  7. 彻底解决tensorflow:ImportError: Could not find 'cudart64_90.dll' tensorflow安装
  8. LeetCode简单题之判断国际象棋棋盘中一个格子的颜色
  9. Camera ISP技术
  10. 客快物流大数据项目(十二):Docker的迁移与备份