生活随笔
收集整理的這篇文章主要介紹了
多任务的死锁问题
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
文章目錄
- 1 多任務(wù)的死鎖問題
- 1.1 死鎖示例
- 1.2 死鎖的概念
- 1.3 應(yīng)對死鎖
1 多任務(wù)的死鎖問題
1.1 死鎖示例
代碼如下:
#include "tinyOS.h"
#include "app.h"
#include "hal.h"static tTask task1
;
static tTask task2
;
static tTask task3
;
static tTask task4
; static tTaskStack task1Env
[TASK1_ENV_SIZE
];
static tTaskStack task2Env
[TASK2_ENV_SIZE
];
static tTaskStack task3Env
[TASK3_ENV_SIZE
];
static tTaskStack task4Env
[TASK4_ENV_SIZE
]; int task1Flag
;
int task2Flag
;
int task3Flag
;
int task4Flag
; static tMutex mutexA
;
static tMutex mutexB
;
void task1Entry
(void *param
) {for (;;) {tMutexWait(&mutexA
, 0);interruptByOtherTask(); tMutexWait(&mutexB
, 0);task1Flag
= 1;tTaskDelay(1);task1Flag
= 0;tTaskDelay(1);tMutexNotify(&mutexB
);tMutexNotify(&mutexA
); task1Flag
= 1;tTaskDelay(1);task1Flag
= 0;tTaskDelay(1); }
}
void task2Entry
(void *param
) {for (;;) {tMutexWait(&mutexB
, 0);interruptByOtherTask(); tMutexWait(&mutexA
, 0);task2Flag
= 1;tTaskDelay(1);task2Flag
= 0;tTaskDelay(1);tMutexNotify(&mutexA
);tMutexNotify(&mutexB
);task2Flag
= 1;tTaskDelay(1);task2Flag
= 0;tTaskDelay(1);}
}
void task3Entry
(void *param
) {for (;;) {task3Flag
= 1;tTaskDelay(1);task3Flag
= 0;tTaskDelay(1);}
}
void task4Entry
(void *param
) {for (;;) {task4Flag
= 1;tTaskDelay(1);task4Flag
= 0;tTaskDelay(1);}
}
void tInitApp
(void) {halInit();tMutexInit(&mutexA
);tMutexInit(&mutexB
);tTaskInit(&task1
, task1Entry
, (void *) 0x0, TASK1_PRIO
, task1Env
, sizeof(task1Env
));tTaskInit(&task2
, task2Entry
, (void *) 0x0, TASK2_PRIO
, task2Env
, sizeof(task2Env
));tTaskInit(&task3
, task3Entry
, (void *) 0x0, TASK3_PRIO
, task3Env
, sizeof(task3Env
));tTaskInit(&task4
, task4Entry
, (void *) 0x0, TASK4_PRIO
, task4Env
, sizeof(task4Env
));
}
1.2 死鎖的概念
兩個或兩個以上的任務(wù)在執(zhí)行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去。此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱為死鎖進(jìn)程。
死鎖產(chǎn)生條件:
以上幾個條件,其中互斥、非剝奪一般是我們所用RTOS默認(rèn)支持,其余條件則由實際應(yīng)用、程序員編寫方式?jīng)Q定。
1.3 應(yīng)對死鎖
預(yù)防死鎖:
為了避免死鎖產(chǎn)生影響整個系統(tǒng)的運行,有三種方式:
- 預(yù)防:破壞產(chǎn)生的幾個條件,容易直觀。
- 避免:分配資源前檢查,如發(fā)生死鎖則不分配,避免死鎖。
- 檢測和恢復(fù):按一定的策略檢測是否有死鎖,然后恢復(fù)。
以上幾種方式,對我們所用的RTOS而言,一般只能做到預(yù)防。而具體的預(yù)防措施,其原理在于打破死鎖產(chǎn)生的幾個條件。根據(jù)前面的死鎖條件,我們只能對控制"請求保持"、“循環(huán)等待” 這兩個條件施加影響。
具體解決:
- 一性全部分配資源,盡可能避免請求和等待。借助等待資源的超時機(jī)制,中間雖有可能發(fā)生死鎖,但由于超時釋放了已申請的資源,避免了超時等待。
#include "tinyOS.h"
#include "app.h"
#include "hal.h"static tTask task1
;
static tTask task2
;
static tTask task3
;
static tTask task4
; static tTaskStack task1Env
[TASK1_ENV_SIZE
];
static tTaskStack task2Env
[TASK2_ENV_SIZE
];
static tTaskStack task3Env
[TASK3_ENV_SIZE
];
static tTaskStack task4Env
[TASK4_ENV_SIZE
]; int task1Flag
;
int task2Flag
;
int task3Flag
;
int task4Flag
; static tMutex mutexA
;
static tMutex mutexB
;
void task1Entry
(void *param
) {for (;;) {do {int error
= 0;tMutexWait(&mutexA
, 0);interruptByOtherTask(); error
= tMutexWait(&mutexB
, 10);if (error
== tErrorNoError
) {break;}tMutexNotify(&mutexA
); } while (1);task1Flag
= 1;tTaskDelay(1);task1Flag
= 0;tTaskDelay(1);tMutexNotify(&mutexB
);tMutexNotify(&mutexA
); task1Flag
= 1;tTaskDelay(1);task1Flag
= 0;tTaskDelay(1); }
}
void task2Entry
(void *param
) {for (;;) {tMutexWait(&mutexB
, 0);interruptByOtherTask(); tMutexWait(&mutexA
, 0);task2Flag
= 1;tTaskDelay(1);task2Flag
= 0;tTaskDelay(1);tMutexNotify(&mutexA
);tMutexNotify(&mutexB
);task2Flag
= 1;tTaskDelay(1);task2Flag
= 0;tTaskDelay(1);}
}
void task3Entry
(void *param
) {for (;;) {task3Flag
= 1;tTaskDelay(1);task3Flag
= 0;tTaskDelay(1);}
}
void task4Entry
(void *param
) {for (;;) {task4Flag
= 1;tTaskDelay(1);task4Flag
= 0;tTaskDelay(1);}
}
void tInitApp
(void) {halInit();tMutexInit(&mutexA
);tMutexInit(&mutexB
);tTaskInit(&task1
, task1Entry
, (void *) 0x0, TASK1_PRIO
, task1Env
, sizeof(task1Env
));tTaskInit(&task2
, task2Entry
, (void *) 0x0, TASK2_PRIO
, task2Env
, sizeof(task2Env
));tTaskInit(&task3
, task3Entry
, (void *) 0x0, TASK3_PRIO
, task3Env
, sizeof(task3Env
));tTaskInit(&task4
, task4Entry
, (void *) 0x0, TASK4_PRIO
, task4Env
, sizeof(task4Env
));
}
- 調(diào)整資源申請順序:避免出現(xiàn)循環(huán)等待。
#include "tinyOS.h"
#include "app.h"
#include "hal.h"static tTask task1
;
static tTask task2
;
static tTask task3
;
static tTask task4
; static tTaskStack task1Env
[TASK1_ENV_SIZE
];
static tTaskStack task2Env
[TASK2_ENV_SIZE
];
static tTaskStack task3Env
[TASK3_ENV_SIZE
];
static tTaskStack task4Env
[TASK4_ENV_SIZE
]; int task1Flag
;
int task2Flag
;
int task3Flag
;
int task4Flag
; static tMutex mutexA
;
static tMutex mutexB
;
void task1Entry
(void *param
) {for (;;) {tMutexWait(&mutexA
, 0);interruptByOtherTask(); tMutexWait(&mutexB
, 0);task1Flag
= 1;tTaskDelay(1);task1Flag
= 0;tTaskDelay(1);tMutexNotify(&mutexB
);tMutexNotify(&mutexA
); task1Flag
= 1;tTaskDelay(1);task1Flag
= 0;tTaskDelay(1); }
}
void task2Entry
(void *param
) {for (;;) {tMutexWait(&mutexA
, 0);interruptByOtherTask(); tMutexWait(&mutexB
, 0);task2Flag
= 1;tTaskDelay(1);task2Flag
= 0;tTaskDelay(1);tMutexNotify(&mutexB
);tMutexNotify(&mutexA
);task2Flag
= 1;tTaskDelay(1);task2Flag
= 0;tTaskDelay(1);}
}
void task3Entry
(void *param
) {for (;;) {task3Flag
= 1;tTaskDelay(1);task3Flag
= 0;tTaskDelay(1);}
}
void task4Entry
(void *param
) {for (;;) {task4Flag
= 1;tTaskDelay(1);task4Flag
= 0;tTaskDelay(1);}
}
void tInitApp
(void) {halInit();tMutexInit(&mutexA
);tMutexInit(&mutexB
);tTaskInit(&task1
, task1Entry
, (void *) 0x0, TASK1_PRIO
, task1Env
, sizeof(task1Env
));tTaskInit(&task2
, task2Entry
, (void *) 0x0, TASK2_PRIO
, task2Env
, sizeof(task2Env
));tTaskInit(&task3
, task3Entry
, (void *) 0x0, TASK3_PRIO
, task3Env
, sizeof(task3Env
));tTaskInit(&task4
, task4Entry
, (void *) 0x0, TASK4_PRIO
, task4Env
, sizeof(task4Env
));
}
參考資料:
手把手教你學(xué)用嵌入式操作系統(tǒng)
總結(jié)
以上是生活随笔為你收集整理的多任务的死锁问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。