ucos-II全局变量、事件、信号量集标志组分别实现哲学家就餐问题

哲学家就餐问题

    有5个哲学家,其生活方式是交替的进行思考和进餐。他们共用一张圆桌,分别坐在周围的5张椅子上,在圆桌上有五个碗和五支筷子,平时哲学家进行思考,饥饿时便试图取其左、右靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐毕,放下筷子继续思考,要求如下:

  • 键盘上的按键0到1分别代表5个哲学家申请吃饭。
  • 要求列出所有可能出现的状况,而且屏幕上必须将最新的状态显示出来。注:申请进餐未果维持5s后改为显示正在思考。
  • 每位哲学家的进餐时间为20s(需要显示倒计时),进餐次数不做限定。
  • 分别用全局变量(不用事件和信号量集标志组)、事件、信号量集标志组实现。

全局变量实现:

#include "INCLUDES.H"
#define TASK_SIZE_STK 512
#define TIME 40
OS_STK StartTaskStk[TASK_SIZE_STK];
OS_STK PhiTaskStk[5][TASK_SIZE_STK];
OS_STK KeyTaskStk[TASK_SIZE_STK];
INT8U x = 0, y = 0;
INT16S Key;
BOOLEAN KeyFlag;
INT8U PhiID[] = {1, 2, 3, 4, 5};   //哲学家编号
INT8U Stick[] = {1, 1, 1, 1, 1};   //全局变量,1代表筷子未被占用
INT16S KeyArray[] = {0x1B, 0x31, 0x32, 0x33, 0x34, 0x35};
//对应Esc,1,2,3,4,5按键
INT8U i;

void StartTask(void *pdata);
void PhiTask(void *pdata);
void KeyTask(void *pdata);
void Eat(INT8U x);
void Think(INT8U x);
void Fail(INT8U x);
void Reply(INT8U x);

void main()
{
    OSInit();
    PC_DOSSaveReturn();
    PC_VectSet(uCOS, OSCtxSw);
    OSTaskCreate(StartTask, (void *)0,
                 &StartTaskStk[TASK_SIZE_STK - 1], 0);
    OSTaskCreate(KeyTask, (void *)0,
                 &KeyTaskStk[TASK_SIZE_STK - 1], 1);
    OSStart();
}

void StartTask(void *pdata)
{
    INT8U err;
    char temp[50];
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR cpu_sr
#endif
    pdata = pdata;
    OS_ENTER_CRITICAL();
    PC_VectSet(0x08, OSTickISR);
    PC_SetTickRate(OS_TICKS_PER_SEC);
    OS_EXIT_CRITICAL();
    OSStatInit();
    for(i = 0; i < 5; i++)
    {
        err = OSTaskCreate(PhiTask, (void *)&PhiID[i],
                           &PhiTaskStk[i][TASK_SIZE_STK - 1], i + 2);
        if(err == OS_NO_ERR)
        {
            sprintf(temp, "Task %d create successfully", i);
            PC_DispStr(2, 20 + i, temp,
                       DISP_BGND_BLACK + DISP_FGND_WHITE);
        }
    }
    //创建完成后挂起自己
    OSTaskSuspend(OS_PRIO_SELF);
}

void KeyTask(void *pdata)
{
    pdata = pdata;
    for(;;)
    {
        KeyFlag = PC_GetKey(&Key);
        if(Key == KeyArray[0])
        {
            PC_DOSReturn();
        }
        OSTimeDly(1);
    }
}

void PhiTask(void *pdata)
{
    //这里只能用局部变量,即为5个任务单独分配空间
    INT8U ID;
    char temp[50];
    INT8U j;
    INT32U time = 0;
    pdata = pdata;
    ID = *(INT8U *)pdata;

    for(;;)
    {
        //读取到相应的按键
        if(Key == KeyArray[ID])
        {
            for(j = 0; j < 5; j++)
            {
                if(Stick[ID - 1] == 1 && Stick[ID % 5] == 1)
                {
                    Stick[ID - 1] = 0;
                    Stick[ID % 5] = 0;
                    j = 6;
                    Eat(ID);
                }
                else if(j < 4)
                {
                    //显示申请
                    Reply(ID);
                }
                else if(j == 4)
                {
                    //已经5s还不满足条件
                    Fail(ID);
                }
                else
                {
                    Think(ID);
                }
                OSTimeDlyHMSM(0, 0, 1, 0);
            }
            OSTimeDly(1);
        }
        else
        {
            Think(ID);
            OSTimeDly(1);
        }
    }
}

void Eat(INT8U ID)
{
    INT8U j;
    char temp[50];
    sprintf(temp, "Philos %d is eating                   ", ID);
    PC_DispStr(x, ID, temp,
               DISP_BGND_BLACK + DISP_FGND_WHITE);

    for(j = TIME; j < 60; j++)
    {
        if(j < 60)
        {
            //倒计时从60 - TIME开始
            sprintf(temp, "countdown: %d s ", 60 - j);
            PC_DispStr(24, ID, temp, DISP_BGND_BLACK + DISP_FGND_GREEN);
            OSTimeDlyHMSM(0, 0, 1, 0);
        }
        if(j == 59)
        {
            Stick[ID - 1] = 1;
            Stick[ID % 5] = 1;
            OSTimeDly(1);
        }
    }
}

void Think(INT8U ID)
{
    char temp[50];
    sprintf(temp, "Philos %d is thinking                   ", ID);
    PC_DispStr(x, ID, temp,
               DISP_BGND_BLACK + DISP_FGND_WHITE);
}

void Fail(INT8U ID)
{
    char temp[50];
    sprintf(temp, "Philos %d apply for meal failed ", ID);
    PC_DispStr(x, ID, temp, DISP_BGND_BLACK + DISP_FGND_RED);
}

void Reply(INT8U ID)
{
    char temp[50];
    sprintf(temp, "Philos %d is replying for meal  ", ID);
    PC_DispStr(x, ID, temp, DISP_BGND_BLACK + DISP_FGND_RED);
    //申请的过程中如果也满足了条件,则同样跳转至Eat函数
    if(Stick[ID - 1] == 1 && Stick[ID % 5] == 1)
    {
        Stick[ID - 1] = 0;
        Stick[ID % 5] = 0;
        Eat(ID);
    }
}

事件实现:

#include "INCLUDES.H"
#define TASK_SIZE_STK 512
#define TIME 50
OS_STK StartTaskStk[TASK_SIZE_STK];
OS_STK PhiTaskStk[5][TASK_SIZE_STK];
OS_STK KeyTaskStk[TASK_SIZE_STK];
INT8U PhiID[] = {1, 2, 3, 4, 5};
INT8U x = 0, y = 0;
INT8U i;
INT16S Key;
BOOLEAN KeyFlag;
INT16S KeyArray[] = {0x1B, 0x31, 0x32, 0x33, 0x34, 0x35};
OS_EVENT *Semp[5];  //声明5个信号量

void StartTask(void *pdata);
void PhiTask(void *pdata);
void KeyTask(void *pdata);
void Eat(INT8U ID);
void Think(INT8U ID);
void Fail(INT8U ID);
void Reply(INT8U ID);

void main()
{
    OSInit();
    PC_DOSSaveReturn();
    PC_VectSet(uCOS, OSCtxSw);
    OSTaskCreate(StartTask, (void *)0,
                 &StartTaskStk[TASK_SIZE_STK - 1], 0);
    OSTaskCreate(KeyTask, (void *)0,
                 &KeyTaskStk[TASK_SIZE_STK - 1], 1);
    OSStart();
}

void StartTask(void *pdata)
{
    INT8U err;
    char temp[50];
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR cpu_sr
#endif
    pdata = pdata;
    OS_ENTER_CRITICAL();
    PC_VectSet(0x08, OSTickISR);
    PC_SetTickRate(OS_TICKS_PER_SEC);
    OS_EXIT_CRITICAL();
    OSStatInit();
    for(i = 0; i < 5; i++)
    {
        err = OSTaskCreate(PhiTask, (void *)&PhiID[i],
                           &PhiTaskStk[i][TASK_SIZE_STK - 1], i + 2);
        if(err == OS_NO_ERR)
        {
            sprintf(temp, "Task %d Creats Successfully", i);
            PC_DispStr(2, 20 + i, temp,
                       DISP_FGND_WHITE + DISP_BGND_BLACK);
        }
        //定义5个信号量,初值为1
        Semp[i] = OSSemCreate(1);
        if(Semp[i] != (OS_EVENT *)0)
        {
            sprintf(temp, "Semphore %d Creates Successfully", i);
            PC_DispStr(40, 20 + i, temp,
                       DISP_BGND_BLACK + DISP_FGND_WHITE);
        }
    }
    OSTaskSuspend(OS_PRIO_SELF);

}

void KeyTask(void *pdata)
{
    pdata = pdata;
    for(;;)
    {
        KeyFlag = PC_GetKey(&Key);
        if(Key == KeyArray[0])
        {
            PC_DOSReturn();
        }
        OSTimeDly(1);
    }
}

void PhiTask(void *pdata)
{
    char temp[50];
    INT8U err1, err2;
    INT32U  time;
    INT8U ID;
    pdata = pdata;
    ID = *(INT8U *)pdata;
    for(;;)
    {
        if(Key == KeyArray[ID])
        {
 
            sprintf(temp, "Philos %d is applying for meal ", ID);
            PC_DispStr(x, ID, temp, DISP_BGND_BLACK + DISP_FGND_RED);
          
            time = OSTimeGet();
            OSSemPend(Semp[ID - 1], 1000, &err1);
            time = OSTimeGet() - time;
            OSSemPend(Semp[ID % 5], 1001 - time, &err2);
            if(err1 == OS_NO_ERR && err2 == OS_NO_ERR)
            {
                //都申请成功,直接跳转到Eat函数
                Eat(ID);
            }
            else if(err1 == OS_NO_ERR && err2 == OS_TIMEOUT)
            {
                OSSemPost(Semp[ID - 1]);
                Fail(ID);
            }
            else if(err1 == OS_TIMEOUT && err2 == OS_NO_ERR)
            {
                OSSemPost(Semp[ID % 5]);
                Fail(ID);
            }
            else
            {
                Think(ID);
            }
            OSTimeDly(1);
        }
        else
        {
            Think(ID);
            OSTimeDly(1);
        }
    }
}

void Eat(INT8U ID)
{
    char temp[50];
    INT8U j;
    sprintf(temp, "Philos %d is eating               ", ID);
    PC_DispStr(x, ID, temp,
               DISP_FGND_WHITE + DISP_BGND_BLACK);
    for(j = TIME; j < 60; j++)
    {
        if(j <= 59)
        {
            sprintf(temp, "last time: %d      ", 60 - j);
            PC_DispStr(24, ID, temp,
                       DISP_FGND_WHITE + DISP_BGND_BLACK);
            OSTimeDlyHMSM(0, 0, 1, 0);
        }
        if(j == 59)
        {
            OSSemPost(Semp[ID - 1]);
            OSSemPost(Semp[ID % 5]);
            OSTimeDly(1);
        }
    }
}

void Think(INT8U ID)
{
    char temp[50];
    sprintf(temp, "Philos %d is thinking                     ", ID);
    PC_DispStr(x, ID, temp,
               DISP_BGND_BLACK + DISP_FGND_WHITE);
}

void Fail(INT8U ID)
{
    char temp[50];
    sprintf(temp, "Philos %d reply for meal failed           ", ID);
    for(i = 0; i < 2; i++)
    {
        PC_DispStr(x, ID, temp,
                   DISP_BGND_BLACK + DISP_FGND_WHITE);
        OSTimeDlyHMSM(0, 0, 0, 400);
    }
}

void Reply(INT8U ID)
{
    char temp[50];
    sprintf(temp, "Philos %d is thinking                     ", ID);
    PC_DispStr(x, ID, temp,
               DISP_BGND_BLACK + DISP_FGND_WHITE);
}

信号量集标志组实现:

#include "INCLUDES.H"
#define TASK_SIZE_STK 512
#define TIME 50
OS_STK StartTaskStk[TASK_SIZE_STK];
OS_STK PhiTaskStk[5][TASK_SIZE_STK];
OS_STK KeyTaskStk[TASK_SIZE_STK];
INT8U PhiID[] = {1, 2, 3, 4, 5};
INT8U x = 0, y = 0;
INT8U i;
INT16S Key;
BOOLEAN KeyFlag;
INT16S KeyArray[] = {0x1B, 0x31, 0x32, 0x33, 0x34, 0x35};
//声明信号量集,只需要1个即可
OS_FLAG_GRP *Semp_F;

INT8U Flag_Location[] = {0, 3, 6, 12, 24, 17};

void StartTask(void *pdata);
void PhiTask(void *pdata);
void KeyTask(void *pdata);
void Eat(INT8U ID);
void Think(INT8U ID);
void Fail(INT8U ID);
void Reply(INT8U ID);

void main()
{
    OSInit();
    PC_DOSSaveReturn();
    PC_VectSet(uCOS, OSCtxSw);
    OSTaskCreate(StartTask, (void *)0,
                 &StartTaskStk[TASK_SIZE_STK - 1], 0);
    OSTaskCreate(KeyTask, (void *)0,
                 &KeyTaskStk[TASK_SIZE_STK - 1], 1);
    OSStart();
}

void StartTask(void *pdata)
{
    INT8U err;
    char temp[50];
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR cpu_sr
#endif
    pdata = pdata;
    OS_ENTER_CRITICAL();
    PC_VectSet(0x08, OSTickISR);
    PC_SetTickRate(OS_TICKS_PER_SEC);
    OS_EXIT_CRITICAL();
    OSStatInit();
    for(i = 0; i < 5; i++)
    {
        err = OSTaskCreate(PhiTask, (void *)&PhiID[i],
                           &PhiTaskStk[i][TASK_SIZE_STK - 1], i + 2);
        if(err == OS_NO_ERR)
        {
            sprintf(temp, "Task %d Creats Successfully", i);
            PC_DispStr(2, 20 + i, temp,
                       DISP_FGND_WHITE + DISP_BGND_BLACK);
        }
    }
    Semp_F = OSFlagCreate(255, &err);
    if(err == OS_NO_ERR)
    {
        sprintf(temp, "OS_FLAG Creats Successfully");
        PC_DispStr(40, 20, temp,
                   DISP_FGND_WHITE + DISP_BGND_BLACK);
    }
    OSTaskSuspend(OS_PRIO_SELF);

}

void KeyTask(void *pdata)
{
    pdata = pdata;
    for(;;)
    {
        KeyFlag = PC_GetKey(&Key);
        if(Key == KeyArray[0])
        {
            PC_DOSReturn();
        }
        OSTimeDly(1);
    }
}

void PhiTask(void *pdata)
{
    char temp[50];
    INT8U errPhi;
    INT8U ID;
    pdata = pdata;
    ID = *(INT8U *)pdata;
    for(;;)
    {
        if(Key == KeyArray[ID])
        {
            sprintf(temp, "Philos %d is applying for meal ", ID);
            PC_DispStr(x, ID, temp, DISP_BGND_BLACK + DISP_FGND_RED);
            OSFlagPend(Semp_F,
                       (OS_FLAGS)Flag_Location[ID],
                       OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME,
                       1000, &errPhi
                      );
            if(errPhi == OS_NO_ERR)
            {
                Eat(ID);
            }
            else
            {
                Fail(ID);
            }
        }
        else
        {
            Think(ID);
            OSTimeDly(1);
        }
    }
}

void Eat(INT8U ID)
{
    char temp[50];
    INT8U j;
    INT8U err;
    sprintf(temp, "Philos %d is eating                    ", ID);
    PC_DispStr(x, ID, temp,
               DISP_FGND_WHITE + DISP_BGND_BLACK);
    for(j = TIME; j < 60; j++)
    {
        if(j <= 59)
        {
            sprintf(temp, "last time: %d      ", 60 - j);
            PC_DispStr(24, ID, temp,
                       DISP_FGND_WHITE + DISP_BGND_BLACK);
            OSTimeDlyHMSM(0, 0, 1, 0);
        }
        if(j == 59)
        {
            OSFlagPost(Semp_F, (OS_FLAGS)Flag_Location[ID], OS_FLAG_SET, &err);
            OSTimeDly(1);
        }
    }
}

void Think(INT8U ID)
{
    char temp[50];
    sprintf(temp, "Philos %d is thinking                     ", ID);
    PC_DispStr(x, ID, temp,
               DISP_BGND_BLACK + DISP_FGND_WHITE);
}

void Fail(INT8U ID)
{
    char temp[50];
    sprintf(temp, "Philos %d reply for meal failed           ", ID);
    for(i = 0; i < 2; i++)
    {
        PC_DispStr(x, ID, temp,
                   DISP_BGND_BLACK + DISP_FGND_WHITE);
        OSTimeDlyHMSM(0, 0, 0, 400);
    }
}

void Reply(INT8U ID)
{
    char temp[50];
    sprintf(temp, "Philos %d is thinking                     ", ID);
    PC_DispStr(x, ID, temp,
               DISP_BGND_BLACK + DISP_FGND_WHITE);
}
  • 12
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值