保护和提供任务之间的通信方法有:
1:通过全局变量
这个是前后台系统最常用的参数传递方式,那么在uc-osII中也可以使用它,只是需要注意一些,譬如说,有两个任务需要对一个全局变量操作,那么在一个任务使用时,另外的一个任务是不能对其操作的,那么,如何做到呢?不切换任务的运行就可以做到,直到对这个全局变量操作完以后才可以进行任务切换,那么这里不让任务切换:1,就是不让节拍中断函数运行,禁止中断,就是进入临界段OS_Enter_Critical();,操作完后,退出临界段OS_Exit_Critical();2,就是设置一个锁,把切换任务的一段上锁OS_Sched_Lock();,使之不让它运行切换任务的程序,在对这个全局变量操作完以后,进行解锁OS_Sched_Un_Lock();,就可以了,后者相当去前者的嵌套;
2:信号量、邮箱、消息队列(邮箱数组)
用这个传递时,需要的是一个事件控制块,因为这3个都可以叫做事件,其中的道理,我也不是很明白,捉摸中
typedef struct { |
void *OSEventPtr; /* 指向消息或者消息队列的指针 */ |
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* 等待任务列表 */ |
INT16U OSEventCnt; /* 计数器(当事件是信号量时) */ |
INT8U OSEventType; /* 事件类型 */ |
INT8U OSEventGrp; /* 等待任务所在的组 */ |
} OS_EVENT; 大家注意:在使用OSSemCreate()时,前面已经创建了一个空闲链表,而这个表是由每一个事件控制块中的OSEventPtr指针指向下一个事件控制块的,而最后一个事件控制块的OSEventPtr指针指向的是空,就是(OS_EVENT *)0,所以有了上面的前提以后,再理解下面的创建一个事件控制块就非常好理解了。 OS_EVENT *OSSemCreate (INT16U cnt) ;该函数返回的数据类型为指针,指针指向的数据类型为OS_EVENT(事件的数据类型为结构体)。也就是函数返回一个地址,地址里存的是新创建的结构体类型所占据的内存的首地址。 OS_EVENT *OSSemCreate (INT16U cnt) { OS_EVENT *pevent; pevent = OSEventFreeList; /*首先创建一个指向OS_EVENT结构体类型的指针pevent*/ /*(OS_EVENT *)0的意思是把0强制转换为OS_EVENT 结构指针,0指*/ /*向的内容为空,但是结构依然占有内存*/ if (OSEventFreeList != (OS_EVENT *)0) { //如果不是空 /* See if pool of free ECB pool was empty */ /*修改指针OSEventFreeList指向下一个,因为在创建空链表时 OSEventFreeList->OSEventPtr就是指向的下一个事件控制块,那么让OSEventFreeList转到下一个。OSEventFreeList,把void类型的OSEventPtr强制转*/
if (pevent != (OS_EVENT *)0) { /*和上面一样,如果事件控制块不为空*/ /*是哪一种类型: #define OS_EVENT_TYPE_UNUSED 0 */ /*没有使用邮箱或者消息队列*/ OS_EventWaitListInit(pevent);通过调用OSEventWaitListInit()对事件控制块中的等待任务列表进行初始化。该函数初始化一个空的等待任务列表,其中没有任何任务。该函数的调用参数只有一个,就是指向需要初始化的事件控制块的指针pevent return (pevent); /*返回创建的结构体类型数据*/ } 信号量的种类与用途: 互斥信号量、二值信号量、计数信号量 互斥的用于解决互斥问题,据说会引起优先级反转的问题 二值的用于解决同步问题 计数的用于解决资源计数问题 比如说你的电脑上有3台打印机,表示有三个资源,那么设置计数信号量为3,如果有一个任务使用了一台打印机,那么计数信号量就减一操作,表示还有2个打印机可用,此时若有另外一个任务也想使用打印机,同样减一操作,假如说同时有四个任务都想使用打印机,而只有3台,那么此时的计数信号量已经为0,所以,有一个任务肯定是需要处于等待状态的 对于邮箱,先建立一个邮箱,它也是一个链表,有邮箱的头和尾,发消息好像就是把消息的地址传给邮箱,相当于插入,或者说申请一个消息资源,对其进行写操作,而接收消息也是接收存储于邮箱中的消息的指针,使用完后归还资源 创建邮箱和创建信号量差不多,不同之处在于事件控制块的类型被设置成OS_EVENT_TYPE_MBOX,以及使用.OSEventPtr域来容纳消息指针,而不是使用.OSEventCnt 域。也就是二者的不同之处在于二者的类型不同:sem 是信息量,使用的的是.OSEventCnt ,用它来表征共享资源的情况,表征有无任务使用共享资源(互斥型信息量)或者是否达到能同时使用该共享资源的任务的最大的数目(计数型信息量),因此我们只用查询.OSEventCnt 变量的具体值就可以判断共享资源的使用情况。 Mbox是消息邮箱,即不同任务传递事件的时候传递的是一个指针,也就是一个地址,这个地址是共享资源的首地址。 OS_EVENT *OSMboxCreate (void *msg)
|
消息队列也可以用于同步,只需将消息队列的缓冲区的长度设置为0,这样单独发送消息的任务将因为没有缓冲区而进入等待状态,而单独接收消息的任务也将没有消息可取而进入等待状态,只有消息的发送和接收都发生了,此时的这两个任务才将得以继续运行,从而达到同步效果
文章评论(0条评论)
登录后参与讨论