zoukankan      html  css  js  c++  java
  • 管道:实用程序服务和数据结构

    管道:实用程序服务和数据结构

    Pipes: utility services and data structures

    管道公用设施             

    Nucleus RTOS有四个API调用,它们提供与管道相关的实用程序函数:重置管道、返回有关管道的信息、返回应用程序中管道的数量以及返回指向应用程序中所有管道的指针。前三个在Nucleus SE中实现。             

    重置管道             

    此API调用将管道恢复到其未使用的初始状态。管道中存储的所有消息都将丢失。在管道上暂停的任何任务都将恢复,并收到NUSE_pipe_WAS_RESET的返回代码。

     

    Nucleus RTOS API Call for Resetting a Pipe

    Service call prototype:

    STATUS NU_Reset_Pipe(NU_PIPE *pipe;

    Parameters:

    pipe – pointer to user-defined pipe control block

    Returns:

    NU_SUCCESS – the call was completed successfully
    NU_INVALID_PIPE – the pipe pointer is not valid

    Nucleus SE API Call for Resetting a Pipe

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

    Service call prototype:

    STATUS NUSE_Pipe_Reset(NUSE_PIPE pipe);

    Parameters:

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

    Returns:

    NUSE_SUCCESS – the call was completed successfully
    NUSE_INVALID_PIPE – the pipe index is not valid

    管道复位的Nucleus-SE实现             

    NUSE_Pipe_Reset()API函数的初始部分(在参数检查之后)非常简单。头和尾索引以及管道的消息计数都设置为零。             

    启用阻塞时,其他代码负责唤醒任何挂起的任务,因此:

    while (NUSE_Pipe_Blocking_Count[pipe] != 0){   U8 index;           /* check whether any tasks are blocked */                                              /* on this 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_PIPE_RESET;         NUSE_Task_Status[index] = NUSE_READY;         break;      }   }   NUSE_Pipe_Blocking_Count[pipe]--;}#if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER   NUSE_Reschedule(NUSE_NO_TASK);#endif

    管道上挂起的每个任务都标记为“就绪”,挂起返回代码NUSE_pipe_WAS_RESET。此过程完成后,如果正在使用优先级调度程序,则会调用NUSE_Reschedule(),因为一个或多个优先级较高的任务可能已准备就绪,需要允许其运行。             

    管道信息             

    此服务调用获取有关管道的信息选择。Nucleus SE实现与Nucleus RTOS的不同之处在于,它返回的信息较少,因为不支持对象命名、可变消息大小和挂起顺序,并且可能无法启用任务挂起。             

    Nucleus RTOS API调用管道信息

    Service call prototype:

    STATUS NU_Pipe_Information(NU_PIPE *pipe, CHAR *name, 
    VOID **start_address,UNSIGNED *pipe_size, UNSIGNED *available, 
    UNSIGNED *messages, OPTION *message_type, UNSIGNED *message_size, 
    OPTION *suspend_type, UNSIGNED *tasks_waiting,
     
    NU_TASK **first_task);

    Parameters:

    pipe – pointer to the user-supplied pipe control block
    name – pointer to an 8-character destination area for the message-pipe’s name
    start_address – a pointer to a pointer, which will receive the address of the start of the pipe’s data area
    pipe_size – a pointer to a variable for holding the total number of bytes in the pipe
    available – a pointer to a variable for holding the number of available bytes in the pipe
    messages – a pointer to a variable for holding the number of messages currently in the pipe
    message_type – pointer to a variable for holding the type of messages supported by the pipe; valid message types are NU_FIXED_SIZE and NU_ VARIABLE_SIZE 
    message_size – pointer to a variable for holding the number of bytes in each pipe message; if the pipe supports variable-length messages, this number is the maximum message size
    suspend_type – pointer to a variable for holding the task suspend type. Valid task suspend types are NU_FIFO and NU_PRIORITY 
    tasks_waiting – a pointer to a variable which will receive the number of tasks suspended on this pipe
    first_task – a pointer to a task pointer; the pointer of the first suspended task is placed in this task pointer

    Returns:

    NU_SUCCESS – the call was completed successfully
    NU_INVALID_PIPE – the pipe pointer is not valid

    Nucleus SE API Call for Pipe Information

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

    Service call prototype:

    STATUS NUSE_Pipe_Information(NUSE_PIPE pipe, 
    ADDR *start_address, U8 *pipe_size, U8 *available, U8 *messages, 
    U8 *message_size, U8 *tasks_waiting, NUSE_TASK *first_task);

    Parameters:

    pipe – the index of the pipe about which information is being requested
    start_address – a pointer to a variable of type ADDR , which will receive the address of the start of the pipe’s data area
    pipe_size – a pointer to a variable of type U8 , which will receive the total number of messages for which the pipe has capacity
    available – a pointer to a variable of type U8 , which will receive the number of messages for which the pipe has currently remaining capacity
    messages – a pointer to a variable of type U8 , which will receive the number of messages currently in the pipe
    message size – a pointer to a variable of type U8 , which will receive the size of messages handled by this pipe
    tasks_waiting – a pointer to a variable which will receive the number of tasks suspended on this pipe (nothing returned if task suspend is disabled)
    first_task – a pointer to a variable of type NUSE_TASK which will receive the index of the first suspended task (nothing returned if task suspend is disabled)

    Returns:

    NUSE_SUCCESS – the call was completed successfully
    NUSE_INVALID_PIPE – the pipe index is not valid
    NUSE_INVALID_POINTER – one or more of the pointer parameters is invalid

    Nucleus SE Implementation of Pipe Information

    The implementation of this API call is quite straightforward:

    *start_address = NUSE_Pipe_Data[pipe];*pipe_size = NUSE_Pipe_Size[pipe];*available = NUSE_Pipe_Size[pipe] - NUSE_Pipe_Items[pipe];*messages = NUSE_Pipe_Items[pipe];*message_size = NUSE_Pipe_Message_Size[pipe];#if NUSE_BLOCKING_ENABLE   *tasks_waiting = NUSE_Pipe_Blocking_Count[pipe];   if (NUSE_Pipe_Blocking_Count[pipe] != 0)   {      U8 index;      for (index=0; index<NUSE_TASK_NUMBER; index++)      {         if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND)              && (HINIB(NUSE_Task_Status[index]) == pipe))         {            *first_task = index;            break;         }      }   }   else   {      *first_task = 0;   }#else   *tasks_waiting = 0;   *first_task = 0;#endif

    函数返回管道状态。然后,如果启用了阻塞API调用,则返回等待的任务数和第一个任务的索引(否则这两个参数设置为0)。             

    获取管道数量             

    此服务调用返回应用程序中配置的管道数。而在Nucleus RTOS中,这将随时间而变化,返回的值将表示当前的管道数,而在Nucleus SE中,返回的值是在构建时设置的,不能更改。

    Nucleus RTOS API Call for Pipe Count

    Service call prototype:

    UNSIGNED NU_Established_Pipes(VOID);

    Parameters:

    None

    Returns:

    The number of created pipes in the system.

    Nucleus SE API Call for Pipe Count

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

    Service call prototype:

    U8 NUSE_Pipe_Count(void);

    Parameters:

    None

    Returns:

    The number of configured pipes in the application

    Nucleus SE Implementation of Pipe Count

    管道计数的Nucleus SE实现             

    这个API调用的实现非常简单:返回#define符号NUSE_PIPE_编号的值。             

    数据结构             

    管道使用六个或七个数据结构—全部在RAM和ROM中—与其他Nucleus SE对象一样,这些数据结构是一系列表,根据配置的管道数量和选择的选项进行包含和标注。             

    我强烈建议应用程序代码不要直接访问这些数据结构,而是使用提供的API函数。这避免了与Nucleus SE未来版本的不兼容和不必要的副作用,并简化了将应用程序移植到Nucleus RTOS的过程。这里包含数据结构的详细信息,以便更容易地理解服务调用代码的工作方式和调试。

    Kernel RAM Data

    These data structures are:

    NUSE_Pipe_Head[] – This is an array of type U8 , with one entry for each configured pipe, which represents a pointer to the front of the pipe of messages. It is used as an index off of the addresses in NUSE_Pipe_Data[] (see below).
    NUSE_Pipe_Tail[] – This is an array of type U8 , with one entry for each configured pipe, which represents a pointer to the end of the pipe of messages. It is used as an index off of the addresses in NUSE_Pipe_Data[] (see below).
    NUSE_Pipe_Items[] – This is an array of type U8 , with one entry for each configured pipe, which represents a count of the current number of messages in the pipe. This data is arguably redundant, as its value can be derived from the head and tail indexes, but storing the count simplifies the code.
    NUSE_Pipe_Blocking_Count[] – This type U8 array contains the counts of how many tasks are blocked on each pipe. This array only exists if blocking API call support is enabled.

    当Nucleus SE启动时,这些数据结构都由NUSE_Init_Pipe()初始化为零。这是合乎逻辑的,因为它将每个管道渲染为空(未使用)。未来的文章将全面描述Nucleus SE的启动过程。              以下是nuse_init.c文件中这些数据结构的定义:

    RAM U8 NUSE_Pipe_Head[NUSE_PIPE_NUMBER];RAM U8 NUSE_Pipe_Tail[NUSE_PIPE_NUMBER];RAM U8 NUSE_Pipe_Items[NUSE_PIPE_NUMBER];#if NUSE_BLOCKING_ENABLE   RAM U8 NUSE_Pipe_Blocking_Count[NUSE_PIPE_NUMBER];#endif

    用户RAM             

    用户应负责为每个配置的管道提供一个RAM区域用于数据存储。这个RAM区域的大小必须容纳一个U8类型的数组,该数组的大小足以容纳管道中的所有消息。

    ROM Data

    These data structures are:

    NUSE_Pipe_Data[] – This is an array of type ADDR , with one entry for each configured pipe, which represents a pointer to the data area (discussed in User RAM above) for each pipe.
    NUSE_Pipe_Size[] – This is an array of type U8 , with one entry for each configured pipe, which represents the number of messages that may be accommodated by each pipe.
    NUSE_Pipe_Message_Size [] – This is an array of type U8 , with one entry for each configured pipe, which represents the size of messages (in bytes) that may be accommodated by each pipe.

    These data structures are all declared and initialized (statically, of course) in nuse_config.c , thus:

    ROM ADDR *NUSE_Pipe_Data[NUSE_PIPE_NUMBER] ={   /* addresses of pipe data areas ------ */};ROM U8 NUSE_Pipe_Size[NUSE_PIPE_NUMBER] ={   /* pipe sizes ------ */};ROM U8 NUSE_Pipe_Message_Size[NUSE_PIPE_NUMBER] ={   /* pipe message sizes ------ */};

    管道数据示意图             

    与Nucleus SE中的所有内核对象一样,管道所需的数据内存量也很容易预测。             

    应用程序中所有管道的ROM数据占用(字节)可以这样计算:             

    NUSE_PIPE_NUMBER * (sizeof(ADDR) + 2)             

    启用阻塞API调用时,应用程序中所有管道的内核RAM数据占用(字节)可以这样计算:

    NUSE_PIPE_NUMBER * 4

    Otherwise it is:

    NUSE_PIPE_NUMBER * 3

    The amount of user RAM (in bytes) required for the pipe with index pipe is:

    NUSE_Pipe_Size[pipe] * NUSE_Pipe_Message_Size[pipe]

    Unimplemented API Calls

    Four pipe API calls found in Nucleus RTOS are not implemented in Nucleus SE:

    Create Pipe

    This API call creates a pipe. It is not needed with Nucleus SE, as pipes are created statically.

    Service call prototype:

    STATUS NU_Create_Pipe(NU_PIPE *pipe, char *name, 
    VOID *start_address, UNSIGNED pipe_size, OPTION message_type, 
    UNSIGNED message_size, OPTION suspend_type);

    Parameters:

    pipe – pointer to a user-supplied pipe control block; this will be used as a “handle” for the pipe in other API calls
    name – pointers to a 7-character, null-terminated name for the pipe
    start_address – starting address for the pipe
    pipe_size – the total number of bytes in the pipe
    message_type – type of message supported by the pipe; may be NU_FIXED_SIZE or NU_VARIABLE_SIZE 
    message_size – if the pipe supports fixed size messages, this parameter specifies the exact size of each message; otherwise, if the pipe supports variable sized messages, this is the maximum message size
    suspend_type – specifies how tasks suspend on the pipe. Valid options for this parameter are NU_FIFOand NU_PRIORITY , which represent First-In-First-Out (FIFO) and priority-order task suspension, respectively

    Returns:

    NU_SUCCESS – indicates successful completion of the service
    NU_INVALID_PIPE – indicates the pipe control block pointer is NULL or already in use
    NU_INVALID_MEMORY – indicates the memory area specified by the start_address is invalid
    NU_INVALID_MESSAGE – indicates that the message_type parameter is invalid
    NU_INVALID_SIZE – indicates that either the message size is greater than the pipe size, or that the pipe size or message size is zero
    NU_INVALID_SUSPEND – indicates that the suspend_type parameter is invalid

    Delete Pipe

    This API call deletes a previously created pipe. It is not needed with Nucleus SE, as pipes are created statically and cannot be deleted.

    Service call prototype:

    STATUS NU_Delete_Pipe(NU_PIPE *pipe);

    Parameters:

    pipe – pointer to pipe control block

    Returns:

    NU_SUCCESS – indicates successful completion of the service
    NU_INVALID_PIPE – indicates the pipe pointer is invalid

    Pipe Pointers

    This API call builds a sequential list of pointers to all pipes in the system. It is not needed with Nucleus SE, as pipes are identified by a simple index, not a pointer, and it would be redundant.

    Service call prototype:

    UNSIGNED NU_Pipe_Pointers(NU_PIPE **pointer_list, 
    UNSIGNED maximum_pointers);

    Parameters:

    pointer_list – pointer to an array of NU_PIPE pointers; this array will be filled with pointers to established pipes in the system
    maximum_pointers – the maximum number of pointers to place in the array

    Returns:

    The number of NU_PIPE pointers placed into the array

    Broadcast to Pipe

    This API call broadcasts a message to all tasks waiting for a message from the specified pipe. It is not implemented with Nucleus SE, as it would have added excessive complexity.

    Service call prototype:

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

    Parameters:

    pipe – pointer to pipe control block
    message – pointer to the broadcast message
    size – the number of UNSIGNED data elements 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 – specifies whether or not to suspend the calling task if the pipe is already full; valid options for this parameter are NU_NO_SUSPEND , NU_SUSPEND or a timeout value.

    Returns:

    NU_SUCCESS – indicates successful completion of the service
    NU_INVALID_PIPE – indicates the pipe pointer is invalid
    NU_INVALID_POINTER – indicates that the message pointer is NULL 
    NU_INVALID_SIZE – Indicates that the message size specified is not compatible with the size specified when the pipe was created
    NU_INVALID_SUSPEND – indicates that suspend attempted from a non-task thread
    NU_PIPE_FULL – indicates that there is insufficient space in the pipe for the message
    NU_TIMEOUT – indicates the pipe is still full after the timeout has expired
    NU_PIPE_DELETED – pipe was deleted while task was suspended
    NU_PIPE_RESET – pipe was reset while the task was suspended

    Compatibility with Nucleus RTOS

    With all aspects of Nucleus SE, it was my goal to maintain as high a level of applications code compatibility with Nucleus RTOS as possible. Pipes are no exception, and, from a user’s perspective, they are implemented in much the same way as in Nucleus RTOS. There are areas of incompatibility, which have come about where I determined that such an incompatibility would be acceptable, given that the resulting code is easier to understand, or, more likely, could be made more memory efficient. Otherwise, Nucleus RTOS API calls may be almost directly mapped onto Nucleus SE calls. A future article will include further information on using Nucleus SE for users of Nucleus RTOS.

    Object Identifiers

    In Nucleus RTOS, all objects are described by a data structure – a control block – which has a specific data type. A pointer to this control block serves as an identifier for the pipe. In Nucleus SE, I decided that a different approach was needed for memory efficiency, and all kernel objects are described by a number of tables in RAM and/or ROM. The size of these tables is determined by the number of each object type that is configured. The identifier for a specific object is simply an index into those tables. So, I have defined NUSE_PIPE as being equivalent to U8 ; a variable – not a pointer – of this type then serves as the pipe identifier. This is a small incompatibility, which is easily handled if code is ported to or from Nucleus RTOS. Object identifiers are normally just stored and passed around and not operated upon in any way.

    Nucleus RTOS also supports naming of pipes. These names are only used for target-based debug facilities. I omitted them from Nucleus SE to save memory.

    Message Size and Variability

    In Nucleus RTOS, a pipe may be configured to handle messages which are comprised of an arbitrary number of bytes of data. Likewise, in Nucleus SE. Nucleus RTOS also supports pipes with variable size messages, where only the maximum size is specified at creation time. Variable size messages are not supported by Nucleus SE.

    Pipe Size

    The number of messages in a pipe in Nucleus SE is limited to 256, as all the index variables and constants are type U8 . Nucleus RTOS is not limited in this way.

    Unimplemented API Calls

    Nucleus RTOS supports ten service calls to work with pipes. Of these, four are not implemented in Nucleus SE. Details of these and of the decision to omit them may be found in Unimplemented API Calls earlier in this article.

    The next RTOS Revealed article will look at system time.

  • 相关阅读:
    hive之insert导入分区数据
    Hive数据倾斜及优化方案
    Hive中join关键字运行机制及使用详解
    如何去编写一个定时器?
    MapReduce运行原理详解
    nfs共享服务搭建
    IDEA中Java方法的抽取
    阿里巴巴开发规约(Alibaba Java Coding Guidelines)安装介绍
    IDEA集成vue
    写给初学asp.net的新人们 新手学习经验
  • 原文地址:https://www.cnblogs.com/wujianming-110117/p/13282250.html
Copyright © 2011-2022 走看看