实验描述:
五个哲学家任务(ph1、ph2、ph3、ph4、ph5)主要有两种过程:思考(即睡眠一段时间)和就餐。每个哲学家任务在就餐前必须申请并获得一左一右两支筷子,就餐完毕后释放这两支筷子。五个哲学家围成一圈,每两人之间有一支筷子。一共有五支筷子,在该实验中用了五个互斥信号量来代表。如下图所示:
实验手册的代码是错误的,看结果就晓得了,相邻的哲学家不可能一块吃饭。
涉及的μC/OS-II系统函数:
。。。
实验代码:
app.c
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
void TaskPhiRepast(
void* pdata)
{ INT8U err; INT8U i,j; /* 第i个哲学家需要第i和j把筷子 */ i = *( int*)pdata; j = (i+ 1) % N_TASKS; while( 1) { printf( "Philosopher %d is hungry... \r\n",i+ 1); OSTimeDly( 500); OSSemPend(ChopStick[i], 0,&err); OSSemPend(ChopStick[j], 0,&err); printf( "Philosopher %d is eating... \r\n",i+ 1); OSTimeDly( 500); printf( "Philosopher %d is thinking... \r\n",i+ 1); OSSemPost(ChopStick[i]); OSSemPost(ChopStick[j]); } } |
app.h
1
2 |
|
GLOBAL OS_EVENT* ChopStick[N_TASKS];
GLOBAL INT8U TaskData[N_TASKS]; |
app_cfg.h
1
2 3 4 5 |
|
#define PHI_REPAST_STK_SIZE
64
#define PHI_REPAST_TASK_Prio 3 #define N_TASKS 5 GLOBAL OS_STK TASK_PHI_REPAST[N_TASKS][PHI_REPAST_STK_SIZE]; void TaskPhiRepast( void* pdata); |
main.c
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
int main(
void)
{ INT8U i; BSP_Init(); OSInit(); for(i = 0;i < N_TASKS;i++) { TaskData[i] = i; ChopStick[i] = OSSemCreate( 1); if(ChopStick[i] != (OS_EVENT*) 0) printf( "ChopStick %d is created no error \r\n",i); } OSTaskCreate( TaskStart, ( void *) 0, //parameter (OS_STK *)&TASK_START_STK[START_STK_SIZE- 1], START_TASK_Prio ); OSStart(); return 0; } |
main.c:TaskStart
1
2 3 4 5 6 7 8 9 10 11 |
|
/* 实验三 信号量:哲学家就餐问题的实现 */ for(i = 0; i < N_TASKS; i++) { err = OSTaskCreate(TaskPhiRepast, ( void *)&TaskData[i], (OS_STK *)&TASK_PHI_REPAST[i][PHI_REPAST_STK_SIZE - 1], PHI_REPAST_TASK_Prio + i); if(err == OS_NO_ERR) { printf( "Philosophor %d is created no error \r\n", i); } } |
实验结果:
注意:如果将信号量的建立放在TaskStart中,则结果出错,出现以下情况,原因未知。
教训:最好将“事件”的建立放在“任务”的建立之前。
感受:多任务系统的调试真心难啊,到处乱跳,而且JLink对硬断点的设置个数有限制(貌似只有6个),一旦设置多了,MDK自动崩溃。(用仿真环境调试,其断点个数貌似没有限制,想设置多少设置多少,但是它不会触发中断和异常。)