接下来需要完成任务间的同步和通信。
任务间同步,为什么需要任务间同步,比如对公共资源的访问,如果不同步,一个任务正在访问资源,另一个任务不知道这个资源正在被访问,也去访问了,这就出现问题了。还有就是任务再等待某一事件的触发,触发后才能运行。实现的一种同步方法就是信号量。何为信号量?举个简单的例子来说,就像是资源的标识,如停车位,当还有停车位时,车才可以停进来,但没有停车位时,外面的车就必须等待,等到有停车位时再进来。下面是一个信号量的简单实现,原理就是用一个全局变量代表可用的资源。当有资源时,这个变量加一,当这个变量为0时代表没有资源了,任务开始挂起,同时开始切换到其它任务。
/*当前信号量列表*/ OS_SEM Sem[MAX_SEM_NUM]; /* * 创建信号量 */ OS_SEM* OSSemCreate(int32 conuter) { OS_CPU_SR cpu_sr = 0; uint32 index; if (conuter < 0) { return (OS_SEM*)NULL; } OS_ENTER_CRITICAL(); for(index=0;index<MAX_SEM_NUM;index++) { if(Sem[index]==-1) { Sem[index]=conuter; OS_EXIT_CRITICAL(); return(Sem[index]); } } OS_EXIT_CRITICAL(); return (OS_SEM*)NULL; } int8 OSSemDelete(OS_SEM* pSem) { OS_CPU_SR cpu_sr = 0; OS_ENTER_CRITICAL(); /*当且仅当信号量计数为0的时候,才能释放该信号量*/ if ((*pSem) != 0) { OS_EXIT_CRITICAL(); return OS_Err; } else { (*pSem) = (OS_SEM)-1; OS_EXIT_CRITICAL(); return OS_OK; } } /*这个是一个不完全精确的实现*/ /*申请信号量*/ /*其超时时间不会非常精确*/ int8 OSSemPend(OS_SEM* pSem,uint32 timeout) { uint32 index; OS_CPU_SR cpu_sr = 0; for (index = 0;index < timeout;index++) { OS_ENTER_CRITICAL(); if ((*pSem) > 0) { (*pSem)--; OS_EXIT_CRITICAL(); return OS_OK;/*获取到了信号量*/ } else { /*等待一个时间片*/ OS_EXIT_CRITICAL(); OSTimeDly(1); } } return OS_Err; } /*不等待,立即返回是否信号量能否获取*/ int8 OSSemGet(OS_SEM* pSem) { OS_CPU_SR cpu_sr = 0; OS_ENTER_CRITICAL(); if ((*pSem) > 0) { (*pSem)--; OS_EXIT_CRITICAL(); return OS_OK;/*获取到了信号量*/ } OS_EXIT_CRITICAL(); return OS_Err; } /*释放(发送)一个信号量*/ int8 OSSemPost(OS_SEM* pSem) { OS_CPU_SR cpu_sr = 0; OS_ENTER_CRITICAL(); (*pSem)++; OS_EXIT_CRITICAL(); return OS_OK; } |