当前位置: 首页 > news >正文

百度联盟怎么做自己的网站网上营销方法

百度联盟怎么做自己的网站,网上营销方法,衡水企业网站建设费用,重庆企业网站seo目录 列表和列表项 关于列表的一些操作 初始化列表 初始化列表项 列表插入列表项 列表项末尾插入 重点 pxIndex指向的是什么 xItemValue存的是什么 vListInsertEnd()的插入位置 List的头尾在哪里? 通用链表的三种实现方式 方法一 方法二 方法三 总结 Fre…

目录

列表和列表项

关于列表的一些操作

初始化列表

 初始化列表项

列表插入列表项

 列表项末尾插入

重点

pxIndex指向的是什么

 xItemValue存的是什么

vListInsertEnd()的插入位置

List的头尾在哪里?

 通用链表的三种实现方式

方法一

 方法二

方法三

总结


FreeRTOS内核调度使用了大量的列表(list)和列表项(listitem)数据结构。它的源码中涉及到很多列表的操作,对于FreeRTOS来说,列表就是它最基础的一部分,列表被用作FreeRTOS调度器使用,用于跟踪任务,处于就绪,挂起,延时的任务都会被挂接到各自的列表中,用户程序如果有需要,也可以使用列表,其中就连FreeRTOS的任务调度其实核心也涉及到列表。

  FreeRTOS列表使用指针指向列表项。一个列表(list)下面可能有很多个列表项(list item),每个列表项都有一个指针指向列表。如图所示

列表和列表项

列表项有两种形式,全功能版的列表项xLIST_ITEM和迷你版的列表项xMINI_LIST_ITEM。我们来看一下它们具体的定义,先看全功能版。

struct xLIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*用于检测列表项数据是否完整*/configLIST_VOLATILE TickType_t xItemValue;           /*列表项值*/struct xLIST_ITEM * configLIST_VOLATILE pxNext;      /*指向列表中下一个列表项*/struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;  /*指向列表中上一个列表项*/void * pvOwner;                                     /*指向一个任务TCB*/void * configLIST_VOLATILE pvContainer;             /*指向包含该列表项的列表 */listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          /*用于检测列表项数据是否完整*/
};
typedef struct xLIST_ITEM ListItem_t;

   宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE用于检查列表项数据是否完整,在projdefs.h中,如果将宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1,则使能列表项数据完整性检查,则宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE会被两个已知的数值代替。

      xItemValue是列表项值,通常是一个被跟踪的任务优先级或是一个调度事件的计数器值。如果任务因为等待从队列取数据而进入阻塞状态,则任务的事件列表项的列表项值保存任务优先级有关信息,状态列表项的列表项值保存阻塞时间有关的信息。这个变量被configLIST_VOLATILE修饰,configLIST_VOLATILE被映射成C语言关键字volatile,表明这个变量是“易变的”,告诉编译器不得对这个变量进行代码优化,因为列表项的成员可能会在中断服务程序中被更新。

  pxNext和pxPrevious是列表项类型指针,用来指向列表中下一个和上一个列表项,通过这两个指针,列表项之间可以形成类似双向链表结构。

      指针pvOwner通常指向一个任务TCB。

      指针pvContainer指向包含该列表项的列表。

      迷你版的列表项xMINI_LIST_ITEM是全功能版列表项xLIST_ITEM的一个子集,定义如下所示:
 

struct xMINI_LIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*用于检测列表项数据是否完整*/configLIST_VOLATILE TickType_t xItemValue;struct xLIST_ITEM * configLIST_VOLATILE pxNext;struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

    既然有了全功能版的列表项,为什么还要声明迷你版的列表项呢?这是因为列表结构体需要一个列表项成员,但又不需要列表项中的所有字段,所以才有了迷你版列表项。迷你列表项起到的主要作用就是标识列表的末尾,所以它的值也设置成了最大值,列表结构体定义为:

typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE                        /*用于检测列表项数据是否完整*/configLIST_VOLATILE UBaseType_t uxNumberOfItems;ListItem_t * configLIST_VOLATILE pxIndex;                   /*用于遍历列表*/MiniListItem_t xListEnd;                                    /*列表项*/listSECOND_LIST_INTEGRITY_CHECK_VALUE                       /*用于检测列表项数据是否完整*/
}List_t;

和列表项定义相同,宏listFIRST_LIST_INTEGRITY_CHECK_VALUE和listSECOND_LIST_INTEGRITY_CHECK_VALUE用于检查列表项数据是否完整,在projdefs.h中,如果将宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1,则使能列表项数据完整性检查,则宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE会被两个已知的数值代替。

      uxNumberOfItems表示该列表中挂接的列表项数目,0表示列表为空。

      列表项类型指针用于遍历列表,列表初始化后,这个指针指向&xListEnd。通过宏listGET_OWNER_OF_NEXT_ENTRY()来获取列表中的下一个列表项。

      列表项xListEnd用于标记列表结束。xListEnd.xItemValue被初始化为一个常数,其值与硬件架构相关,为0xFFFF(16位架构)或者0xFFFFFFFF(32位架构)。
 

关于列表的一些操作

初始化列表

列表结构体中包含一个列表项成员,主要用于标记列表结束。初始化列表就是把这个列表项插入到列表中。

void vListInitialise( List_t * const pxList )
{/*列表索引指向列表项*/pxList->pxIndex = ( ListItem_t * )&( pxList->xListEnd );                  /* 设置为最大可能值 */pxList->xListEnd.xItemValue =portMAX_DELAY;/* 列表项xListEnd的pxNext和pxPrevious指针指向了它自己 */pxList->xListEnd.pxNext = (ListItem_t * ) &( pxList->xListEnd );pxList->xListEnd.pxPrevious= ( ListItem_t * ) &( pxList->xListEnd );pxList->uxNumberOfItems = ( UBaseType_t) 0U;/* 设置为已知值,用于检测列表数据是否完整*/listSET_LIST_INTEGRITY_CHECK_1_VALUE(pxList );listSET_LIST_INTEGRITY_CHECK_2_VALUE(pxList );
}

如果宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1,则使能列表项数据完整性检查,则宏listSET_LIST_INTEGRITY_CHECK_1_VALUE()和listSET_LIST_INTEGRITY_CHECK_2_VALUE被一个已知值代替,默认为0x5a5a(16位架构)或者0x5a5a5a5a(32位架构)。

      假设禁止列表数据完整性检查,初始化后的列表如图1-2所示,uxNumberOfItems被初始化为0,xListEnd.xItemValue初始化为0xffffffff,pxIndex、xListEnd.pxNext和xListEnd.pxPrevious初始化为指向列表项xListEnd。
 

 初始化列表项

列表项的初始化很简答, 只需要声明该列表项不属于任何一个列表就可以了。

void vListInitialiseItem( ListItem_t * const pxItem )
{pxItem->pvContainer = NULL;/*设置为已知值,用于检测列表项数据是否完整*/listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem );listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem );
}

如果宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1,则使能列表项数据完整性检查,则宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE会被两个已知的数值代替,默认为0x5a5a(16位架构)或者0x5a5a5a5a(32位架构)。

      假设禁止列表项数据完整性检查,初始化后的列表项如图1-3所示。仅是将指针pvContainer设置为空指针,该指针用于指向包含该列表项的列表,这里设置为NULL表示这个列表项不属于任何列表。
 

列表插入列表项

每个列表项对象都有一个列表项值(xItemValue),通常是一个被跟踪的任务优先级或是一个调度事件的计数器值。调用API函数vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem)可以将pxNewListItem指向的列表项插入到pxList指向的列表中,列表项在列表的位置由pxNewListItem->xItemValue决定,按照升序排列。

void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t *pxIterator;
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;/* 检查列表和列表项数据的完整性,仅当configASSERT()定义时有效。*/listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY(pxNewListItem );/*将新的列表项插入到列表,根据xItemValue的值升序插入列表。*/if( xValueOfInsertion == portMAX_DELAY){pxIterator =pxList->xListEnd.pxPrevious;}else{for( pxIterator = (ListItem_t * ) &( pxList->xListEnd );pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator =pxIterator->pxNext ){/* 这里为空 */}}pxNewListItem->pxNext =pxIterator->pxNext;pxNewListItem->pxNext->pxPrevious= pxNewListItem;pxNewListItem->pxPrevious =pxIterator;pxIterator->pxNext = pxNewListItem;pxNewListItem->pvContainer = ( void* ) pxList;( pxList->uxNumberOfItems )++;
}

 列表项末尾插入

void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t* const pxIndex = pxList->pxIndex;/*检查列表和列表项数据的完整性,仅当configASSERT()定义时有效。*/listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY(pxNewListItem );/*向列表中插入新的列表项*/pxNewListItem->pxNext = pxIndex;pxNewListItem->pxPrevious =pxIndex->pxPrevious;mtCOVERAGE_TEST_DELAY();pxIndex->pxPrevious->pxNext =pxNewListItem;pxIndex->pxPrevious = pxNewListItem;pxNewListItem->pvContainer = ( void* ) pxList;( pxList->uxNumberOfItems )++;
}

重点

pxIndex指向的是什么

重点:一开始学习的时候,一直不明白这个pxIndex有什么用,因为我在有关列表的list.c中的API函数中根本没发现有改变它的代码,以为它一直是初始化的值,就是一直指向迷你列表项,其实不然,作为一名程序员,一切从源码中得到答案。

搜索代码之后发现,中间对pxIndex赋值的地方只有listGET_OWNER_OF_NEXT_ENTRY这个接口(list.h中的一个有参宏)

 每调用一次listGET_OWNER_OF_NEXT_ENTRY,列表的pxIndex会指向下一个列表项。
而调用listGET_OWNER_OF_NEXT_ENTRY,主要是一下的一些函数接口:

 xItemValue存的是什么

列表项值,都是通过listSET_LIST_ITEM_VALUE这个宏来赋值的。

#define listSET_LIST_ITEM_VALUE( pxListItem, xValue )	( ( pxListItem )->xItemValue = ( xValue ) )

搜了一下,主要赋值了两类值

  • 优先级
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */

可以看到和我们之前说的,设置优先级是在任务的事件列表项中。

  • 醒来时间(对于状态列表)
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );

同理,和之前说的一样,对于任务的阻塞时间,在任务的状态列表项中设置列表项的值。

vListInsertEnd()的插入位置

Tips: 这个函数是最容易造成误解的一个函数,字面理解,在我开始学的时候我以为就是插入到最后一个迷你列表项的前面,所谓末尾插入肯定是最后一项嘛,阅读源码之后,其实不然,因为列表中有一项成员 

ListItem_t * configLIST_VOLATILE pxIndex; 

该成员主要作用就是用来遍历列表的。阅读源码发现它是插入在pxIndex所指的列表项的前面。这里体现了FreeRTOS的哲学理念,“公平”,如果pxIndex,指向的是当前的索引的列表项表示正在使用,这时比如顺序是1->2->3,现在pxIndex指向2,要插入4,这时你4肯定是要最后遍历访问的,意味着就是访问顺序应该是2->3->1->4,所以它要插入在2前面,我的方法是记住一个口诀,末尾插入就是插入pxIndex所指列表项的前一项的后面,可能听着有点别扭(不就是所指列表项的前面嘛🤣 ,细细体会,有公平的哲学思想)

List的头尾在哪里?

结尾是xListEnd吗?

这个是初始化时候的结尾,名字也是结尾。

但是vListInsertEnd又不是根据xListEnd来定的,是插在pxIndex前面的,那有的认为pxIndex就是开头,查了一些资料,头尾好像没有怎么分,但是第二种认可度更高,因为末尾插入是这么用的。

 通用链表的三种实现方式

针对不同的列表项,如果不采用通用的链表处理,就需要实现不同链表的操作函数,实现通用链表有三种实现方式:

方法一

 这样node节点直接就是它的开头,如果你要根据比如dog的age进行排序,直接可以通过node指针把它转成列表项指针就可以访问到它的age属性。

 方法二

这里就要根据node在结构体里的地址,转成列表项的指针进而访问到它的属性,进行排序操作等。这时要计算node在结构体的偏移,可以采用如下方式,结构体地址为0,直接看node的地址。

 Linux和RT-Thread采用这种实现通用链表🤣 

方法三

直接通过container指针就可以知道它属于那种列表项,进而可以访问到其它属性。

 

 

 FreeRTOS采用这种方式实现通用链表🤣,它里面的pvOwner,就是我们上面说的方法三的Container的概念 。

总结

FreeRTOS的列表和列表项采用了一种通用的列表管理,不像我以前学的数据结构中的链表操作一样,其中的节点都是具体的结构体的内容,所以是针对具体的一类结构体,比如struct people,这样导致的后果就是所有有关链表操作的内容都是针对这类结构体,如果稍微改成struct dog,这样就需要全部重写链表的所有操作了。FreeRTOS采用一种方法,写出了通用的链表操作,让我不得不感叹这代码确实是写的好!🤣 

http://www.dt0577.cn/news/48158.html

相关文章:

  • 如何让百度k掉网站湖北seo诊断
  • 秦皇岛网站群发关键词宁波优化网站厂家
  • 成都网站设计公最新nba排名
  • 新乡网站建设-中国互联网络推广运营外包公司
  • 免费自助建手机网站指数工具
  • python做网站教程网站设计制作在哪能看
  • 泰安网站建设流程推广衣服的软文
  • 马鞍山做网站公司排名重庆网站网络推广
  • 织梦dede网站后台被挂黑链怎么办企业培训课程有哪些
  • 最便宜建站优化大师电视版
  • 做网站登录的需求分析百度搜索引擎首页
  • joomla 网站建设教程新闻 最新消息
  • 如何制作一个网站h5网站seo优化建议
  • 网站浏览器图标怎么做如何设置友情链接
  • 有哪些做ppt用图片的网站百度员工收入工资表
  • 专业手机网站有哪些网络广告的形式有哪些?
  • 团队建设思路和方案重庆seo和网络推广
  • 专业营销型网站建设刷关键词排名seo
  • 做微信公众号的是哪个网站吗东莞日增感染人数超25万
  • 网站建设营销型网站免费进入窗口软件有哪些
  • wordpress网站文章形式seo北京网站推广
  • php做的汽车销售网站输入关键词自动生成标题
  • 做网站哪个靠谱西安网站关键词优化推荐
  • 微信公众平台做微网站吗怎么做好市场宣传和推广
  • pc网站还有必要做吗网络营销到底是个啥
  • 福建省第二电力建设公司网站重庆seowhy整站优化
  • 用html网站登录界面怎么做廊坊百度快照优化
  • 空间站 参考消息手机怎么建网站
  • 专业网站建设出售盘古百度推广靠谱吗
  • 婚礼摄影网站源码ip域名查询网站入口