zoukankan      html  css  js  c++  java
  • 【RTOS】RTOS源码基础之队列结构体


    前言

    以下 RTOS 是基于 FreeRTOS 源码分析。
    建议直接看源码去了解。

    李柱明博客:https://www.cnblogs.com/lizhuming/p/15487239.html

    IPC

    本人认为在学习 RTOS 任务间通信时必须了解的一个结构体就是 struct QueueDefinition,其源码参考 附件-源码。
    该结构体被运用到消息队列、二进制信号量、计数信号量、互斥量和递归互斥量等等关于任务间通信的控件。

    这些控件在系统中都是由 控制块 + 存储区 组成,而该结构体就是控制块的角色,管理其对应的存储区。

    成员剖析

    在成员剖析时默认按消息队列的作用去剖析。

    int8_t *pcHead;:

    /* 该队列存储区的起始位置,对应第一个消息空间。*/
    int8_t *pcHead;
    

    int8_t *pcTail;:

    /* 消息队列存储区的结尾位置。
     * 结合 pcHead 指针就是整个存储区合法区域。*/
    int8_t *pcHead;
    

    int8_t *pcWriteTo;:

    /* 写指针,指向存储区中下一个空闲的空间。
     * 队列下次写数据的位置,需要入队时调用该指针写入数据。*/
    int8_t *pcWriteTo;
    

    int8_t *pcReadFrom;:

    /* 读指针,指向存储区中下一个有效数据的空间。
     * 队列下次读取数据的位置,需要出队时调用该指针写入数据。*/
    int8_t *pcReadFrom;
    

    UBaseType_t uxRecursiveCallCount;:

    /* 递归次数。
     * 用于互斥量时使用,与 pcReadFrom 为联合体。
     * 记录递归互斥量被调用的次数。 */
    UBaseType_t uxRecursiveCallCount;
    

    List_t xTasksWaitingToSend;:

    /* 等待发送的任务列表。
     * 当队列存储区满时,需要发送消息的任务阻塞时记录到该链表。
     * 按任务优先级排序。 */
    List_t xTasksWaitingToSend;
    

    List_t xTasksWaitingToReceive;:

    /* 等待接收的任务列表。
     * 当队列存储区为空时,需要获取消息的任务阻塞时记录到该链表。
     * 按任务优先级排序。 */
    List_t xTasksWaitingToReceive;
    

    volatile UBaseType_t uxMessagesWaiting;:

    /* 当前消息节点的个数。
     * 即是当前有效消息数量。
     * 二值信号量、互斥信号量时:表示有无信号量可用。
     * 计数信号量时:有效信号量个数。 */
    volatile UBaseType_t uxMessagesWaiting;
    

    UBaseType_t uxLength;:

    /* 当前队列最大节点总数。
     * 即是最多能存放多少个消息。
     * 二值信号量、互斥信号量时:最大为1。
     * 计数信号量时:最大的信号量个数。 */
    UBaseType_t uxLength;
    

    UBaseType_t uxItemSize;:

    /* 单个节点的大小。
     * 单个消息的大小。
     * 二值信号量、互斥信号量时:0。
     * 计数信号量时:0。 */
    UBaseType_t uxItemSize;
    

    volatile int8_t cRxLock;:

    /* 记录出队的数据项个数。
     * 即是需要解除多少个阻塞在接收等待列表中的任务。 */
    volatile int8_t cRxLock;
    

    volatile int8_t cTxLock;:

    /* 记录入队的数据项个数。
     * 即是需要解除多少个阻塞在发送等待列表中的任务。 */
    volatile int8_t cTxLock;
    

    cRxLock 和 cTxLock

    当中断服务程序操作队列并且导致阻塞的任务解除阻塞时。
    首先判断该队列是否上锁:

    • 如果没有上锁,则解除被阻塞的任务,还会根据需要设置上下文切换请求标志;
    • 如果队列已经上锁,则不会解除被阻塞的任务,取而代之的是,将 xRxLock 或 xTxLock 加 1,表示队列上锁期间出队或入队的数目,也表示有任务可以解除阻塞了。

    cRxLock 对应待出队的个数。
    cTxLock 对应待入队的个数。

    触发解除阻塞

    触发解除阻塞的方式:

    • 收发消息。

      • 即是数据项出入队时,会触发阻塞的任务解除阻塞。
    • 超时。

      • 超时也会触发对应的阻塞任务解除阻塞。
    • 解锁后处理上锁时未处理的出入队。

      • cRxLock 和 cTxLock。

    附件-源码

    /*
     * Definition of the queue used by the scheduler.
     * Items are queued by copy, not reference.  See the following link for the
     * rationale: http://www.freertos.org/Embedded-RTOS-Queues.html
     */
    typedef struct QueueDefinition
    {
    	int8_t *pcHead;					/*< Points to the beginning of the queue storage area. */
    	int8_t *pcTail;					/*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
    	int8_t *pcWriteTo;				/*< Points to the free next place in the storage area. */
    
    	union							/* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
    	{
    		int8_t *pcReadFrom;			/*< Points to the last place that a queued item was read from when the structure is used as a queue. */
    		UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
    	} u;
    
    	List_t xTasksWaitingToSend;		/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
    	List_t xTasksWaitingToReceive;	/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */
    
    	volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */
    	UBaseType_t uxLength;			/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
    	UBaseType_t uxItemSize;			/*< The size of each items that the queue will hold. */
    
    	volatile int8_t cRxLock;		/*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
    	volatile int8_t cTxLock;		/*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
    
    	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
    		uint8_t ucStaticallyAllocated;	/*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
    	#endif
    
    	#if ( configUSE_QUEUE_SETS == 1 )
    		struct QueueDefinition *pxQueueSetContainer;
    	#endif
    
    	#if ( configUSE_TRACE_FACILITY == 1 )
    		UBaseType_t uxQueueNumber;
    		uint8_t ucQueueType;
    	#endif
    
    } xQUEUE;
    
  • 相关阅读:
    临时表各方式对比
    【译】表变量和临时表的比较(转)
    delete和truncate的一个严重区别
    各种临时表插入数据方式对比(包括自增列和GUID列)
    纤程模式的问题
    转 javascript针对DOM的应用(四)
    转 CSS兼容性(IE和Firefox)技巧大全 (四)
    转 CSS兼容性(IE和Firefox)技巧大全 (五)
    转 javascript针对DOM的应用(三)
    javascript基础知识大全(1)
  • 原文地址:https://www.cnblogs.com/lizhuming/p/15487239.html
Copyright © 2011-2022 走看看