找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10625|回复: 3
打印 上一主题 下一主题
收起左侧

uc/os-ii操作系统中任务间的同步与通信问题--实例(注释很详细)

[复制链接]
跳转到指定楼层
楼主
本例用了BC4.5软件,在DOS环境模拟uc/os-ii ,这是本人发表在论坛上的一篇笔记;放到这里以便常温故。

最近本人在学习uc/os-ii操作系统,收获真的很大,uc/os-ii系统中我觉得任务间的同步与通信是有点难;本人将学习笔记整理出来放在这里,希望有高人能指出错误的地方,欢迎指教,谢谢!

/*建立两个用户任务:MyTask和YouTask。这两个任务都要访问一个共享资源S,但是YouTask访问需要的时间要长一些,而MYTASK访问的时间要短点,这样就不可避免的出现了在任务YOUTASK访问S期间,任务MYTASK也来访问S,从而出现干扰*/#include "INCLUDES.h"
#define  TASK_STK_SIZE  512       /* 任务堆栈长度*/            
char   ss;
OS_STK        MyTaskStk[TASK_STK_SIZE];
OS_STK        YouTaskStk[TASK_STK_SIZE];
INT8U  y1=0,y2=0;   //字符显示位置  
char *s="原始数据";
void  MyTask(void *data);    /* 声明任务      */
void  YouTask(void *data);
/*
****************************************************************************
*                       MAIN主函数
***************************************************************************
*/
void  main (void)
{
  OSInit();      /* 初始化uC/OS-II   */
  PC_DOSSaveReturn();     /* 保存DOS环境     */
  PC_VectSet(uCOS, OSCtxSw);     /* 安装uC/OS-II的中断 */
  OSTaskCreate(MyTask,(void *)0, &MyTaskStk[TASK_STK_SIZE - 1], 0); /*创建起始函数*/
  OSStart();     /* 启动多任务管理   */
}
/*
**************************************************************************
*       STARTUP TASK
************************************************************************
*/
void  MyTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3    /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
#endif
    INT16S   key;             /*用于退出的建*/
    pdata = pdata;    /* Prevent compiler warning   */
    OS_ENTER_CRITICAL();
    PC_VectSet(0x08, OSTickISR);       /* 安装时钟中断向量  */
    PC_SetTickRate(OS_TICKS_PER_SEC);     /* 设置时钟频率 */
    OS_EXIT_CRITICAL();
    OSStatInit();      /* 初始化统计任务   */
    OSTaskCreate(YouTask,(void *)0, &YouTaskStk[TASK_STK_SIZE - 1], 2); /*创建任务函数*/
    for (;;)
    {
     s = "MyTask get source S";
     PC_DispStr(2,++y1,s,DISP_BGND_BLACK+DISP_FGND_WHITE);/*任务*/   
     //如果恩下ESC键,则退出UC/OS-II
        if (PC_GetKey(&key) == TRUE)
         {                     
            if (key == 0x1B)
            {         
                PC_DOSReturn();     /* Return to DOS  */
            }
        }
        OSTimeDly(500);   /* 等待500个时钟节拍 */
    }
}

void  YouTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3   /*Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
#endif
INT8U err;
pdata=pdata;
for (;;)
{
  s = "YouTask get source S";
  PC_DispStr(28,++y2,s,DISP_BGND_BLACK+DISP_FGND_WHITE);
  OSTimeSet(0);    /*置OSTime为0,注意此句的作用*/
  while(OSTime<1000)    /*条件语句“OSTime<1000”非常重要!*/
  {
   //sprintf(ss,"%d",OSTimeGet());
   PC_DispStr(55,y2,s,DISP_BGND_BLACK+DISP_FGND_WHITE);/*本实验的精髓语句*/
  }     
        OSTimeDly(100);    //等待100个时钟节拍               
    }
}
/*在YOUTASK访问资源S期间高优先级的任务MYTASK也访问了S,从而干扰了任务YOUTASK对共享资源S的访问,运行后显示表明在任务YOUTASK的延时期间前,共享资源S的内容发生了变化。笔记:
YouTask任务分析:在YouTask任务中程序代码虽然较少但是程序流程相当复杂!必须搞懂每句的含义,提高程序分析能力!分析程序一定要注意流程!下面将YouTask任务中重要部分语句(红色注释部分)分析如下:
1,在MyTask任务挂起同时执行“PC_DispStr(28,++y2,s,DISP_BGND_BLACK+DISP_FGND_WHITE);”语句,所以在显示屏相应的位置几乎同时显示"MyTask get source S"和"YouTask get source S";
2,操作系统的每个任务都在for死循环里完成;“OSTimeSet(0);”语句的意思是,每进入一次for循环里就给系统时间全局变量OSTime重新赋值,在这里就是将OSTime清零;为下一语句“while(OSTime<1000)”做铺垫;
3,本任务中有两个循环体,另一个就是“while(OSTime<1000)”,因为前面有“OSTimeSet(0);”语句,所以系统每次进入YOUTASK任务的for循环里都会执行“while(OSTime<1000)”语句,进入“while(OSTime<1000)”语句之后,全局变量OSTime会以设定的时钟节拍不断自加1,当全局变量OSTime等于1000时,系统就会退出“while(OSTime<1000)”语句,执行“ OSTimeDly(100);”语句,也就是说在OSTime的值在0到1000的时间段里程序会一直执行“PC_DispStr(55,y2,s,DISP_BGND_BLACK+DISP_FGND_WHITE);”语句,即显示相应的内容;
4,因为在YouTask任务中有两句即“PC_DispStr(28,y2,s,DISP_BGND_BLACK+DISP_FGND_WHITE);”语句和
“PC_DispStr(55,y2,s,DISP_BGND_BLACK+DISP_FGND_WHITE);”语句,这样就会在同一个任务中出现争抢s资源的现象(即在内存同一位置几乎同时被赋不同的值)而造成程序出错干扰,这是不允许的!。所以在实验现象中在“55,y2”坐标处先显示“YouTask get source S”再变成显示"MyTask get source SS"的现象。
5,注意:a,在死循环for里才是要创建任务的内容,换句话说任务需要执行的内容只能写在死循环for里;b,本实验中,两个任务都应用了“OSTimeDly(ticks)”函数,当两个任务同时挂起时系统运行哪个任务呢?操作系统不会让cpu闲着,这时会选择优先级最高的任务运行!
6,系统进入YouTask任务时,执行“PC_DispStr(28,++y2,s,DISP_BGND_BLACK+DISP_FGND_WHITE);”语句,在显示屏相应的位置显示"MyTask get source S",接着进入while循环执行
“PC_DispStr(55,y2,s,DISP_BGND_BLACK+DISP_FGND_WHITE);”语句即显示"YouTask get source S",程序很快就会退出while循环执行下面的“ OSTimeDly(100);”语句即挂起YouTask任务,就在挂起YouTask任务的同时系统选择运行MyTask任务,s同时被赋值为"MyTask get source S",所以在实验现象中就出现在“55,y2”坐标处先显示“YouTask get source S”再马上变成显示"MyTask get source SS"的现象(为什么是两个“SS”?)。
7,本实验中MyTask任务占用CPU的时长由程序代码的精度决定。可以通过实验验证。
8,在时序上,s先在MyTask任务中被赋值,再执行YouTask任务s再次被赋值,接着还是在YouTask任务的while中s 再次被赋值;在这个过程中两个任务没有对s资源发生争抢,而在YouTask任务的“ OSTimeDly(100);”语句中两个任务对s资源发生了争抢,导致出现“55,y2”处出现干扰。


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩1
回复

使用道具 举报

沙发
ID:201329 发表于 2018-4-10 21:47 | 只看该作者
楼主很认真,赞一个。在此提出自己的一点看法,不吝赐教。
1、MyTask先运行,在第一列打印出“MyTask get source S”。在MyTask任务OSTimeDly(500)期间,操作系统进行任务调度,此时,就绪的YouTask开始运行,在第二列打印出“YouTask get source S”。
2、 OSTimeSet(0)使OSTime变量置零,进入while(OSTime<1000)循环。因为此时MyTask任务控制块的OSTCBDLY变量还未为0【OSTimeDly(500)设置MyTask任务控制块的OSTCBDLY变量为500】,即MyTask还处于未就绪状态,所以一直在while(OSTime<1000)循环内第三列打印“YouTask get source S”
3、当OSTime还未计到1000而MyTask任务OSTimeDly(500)已经完成【即MyTask任务控制块的OSTCBDLY变为0】,MyTask任务就绪,操作系统再次进行任务调度,就绪的MyTask开始运行,在第一列打印出“MyTask get source S”。同时改变s变量的值。4、 MyTas再次进入运行OSTimeDly(500),系统返回YouTask任务的while(OSTime<1000)循环继续执行。因为s变量已经在MyTask中改变,所以可以看到输出窗口第三列先输出“YouTask get source S”,随后即变为“MyTask get source S”。【因为You是三个字节,My是两个字节,所以“YouTask get source S”最后的S没有抹除,所以会出现显示"MyTask get source SS"的现象】
5、当OSTime还未计到1000而MyTask任务OSTimeDly(500)又已经完成【因为第一次系统从MyTask任务调度到YouTask任务以及YouTask任务的执行花费了时间,MyTask任务控制块的OSTCBDLY变量的值其实已经小于500了】,操作系统再调MyTas,在第一列打印出“MyTask get source S”。
6、OSTime终于计到1000,又进入了YouTask任务OSTimeDly(100)。此时两个任务都没有就绪,系统调度空闲任务。随后YouTask首先就绪,在第二列又打出“YouTask get source S”。


总结:任务资源共享干扰发生在3。程序运行果如图


20180410214632.png (8.33 KB, 下载次数: 126)

20180410214632.png

评分

参与人数 1黑币 +80 收起 理由
admin + 80 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:523499 发表于 2019-4-28 11:13 来自手机 | 只看该作者
请问 在youtask中的while如何在mytask延时到的时候就发生任务调度
回复

使用道具 举报

地板
ID:137412 发表于 2019-6-11 14:03 | 只看该作者
2015年的帖子,到现在都没人纠正其中的错误,也是蛮悲哀的了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表