マルチタスクのデッドロックの問題


文書ディレクトリ
  • 1マルチタスクのデッドロック問題
  • 1.1デッドロック例
  • 1.2デッドロックの概念
  • 1.3デッドロック対応
  • 1マルチタスクのデッドロックの問題
    1.1デッドロックの例
    多任务的死锁问题_第1张图片コードは次のとおりです.
    /**
     * @brief tOS    
     * @details
     * @author 01       http://01ketang.cc
     * @date 2017-06-01
     * @version 1.0
     * @copyright     ,        
     */
    #include "tinyOS.h"
    #include "app.h"
    #include "hal.h"
    
    static tTask task1;                     //   1  
    static tTask task2;                     //   2  
    static tTask task3;                     //   3  
    static tTask task4;                     //   4  
    
    static tTaskStack task1Env[TASK1_ENV_SIZE];     //   1     
    static tTaskStack task2Env[TASK2_ENV_SIZE];     //   2     
    static tTaskStack task3Env[TASK3_ENV_SIZE];     //   3     
    static tTaskStack task4Env[TASK4_ENV_SIZE];     //   4     
    
    int task1Flag;           //                
    int task2Flag;           //                
    int task3Flag;           //                
    int task4Flag;           //                
    
    static tMutex mutexA;
    static tMutex mutexB;
    
    /**
     *        
     * @param param         
     */
    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);        
        }
    }
    
    /**
     *        
     * @param param         
     */
    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);
        }
    }
    
    /**
     *        
     * @param param         
     */
    void task3Entry (void *param) {
        for (;;) {
            task3Flag = 1;
            tTaskDelay(1);
            task3Flag = 0;
            tTaskDelay(1);
        }
    }
    
    
    /**
     *        
     * @param param         
     */
    void task4Entry (void *param) {
        for (;;) {
            task4Flag = 1;
            tTaskDelay(1);
            task4Flag = 0;
            tTaskDelay(1);
        }
    }
    
    /**
     * App    
     */
    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デッドロックの概念
    多任务的死锁问题_第2张图片の2つ以上のタスクは、実行中に競合リソースまたは相互通信によるブロックの現象により、外力の作用がなければ推進できません.このとき、システムがデッドロック状態にあるか、システムがデッドロックを発生していると呼ばれ、これらが永遠に互いに待っているプロセスをデッドロックプロセスと呼ぶ.
    デッドロック発生条件:多任务的死锁问题_第3张图片以上のいくつかの条件で、反発、非剥奪は一般的に私たちが使用しているRTOSのデフォルトサポートであり、残りの条件は実際のアプリケーション、プログラマーの作成方法によって決定されます.
    1.3デッドロックへの対応
    多任务的死锁问题_第4张图片デッドロックの予防:多任务的死锁问题_第5张图片デッドロックがシステム全体の動作に影響を与えないようにするには、3つの方法があります.
  • 予防:発生したいくつかの条件を破壊し、直感的になりやすい.
  • 回避:リソースを割り当てる前にチェックし、デッドロックが発生した場合は割り当てず、デッドロックを回避します.
  • 検出とリカバリ:一定のポリシーでデッドロックがあるかどうかを検出し、リカバリします.

  • 以上のいくつかの方法は,我々が用いているRTOSにとって,一般的には予防しかできない.具体的な予防措置は、デッドロックによるいくつかの条件を破ることにある.前のデッドロック条件に基づいて、制御の「要求保持」、「ループ待機」の2つの条件にのみ影響を与えることができます.
    具体的な解決:
  • は、要求および待機を最小限に抑えるために、リソースをすべて割り当てます.待機リソースのタイムアウトメカニズムにより,途中でデッドロックが発生する可能性があるが,タイムアウトにより申請したリソースが解放され,タイムアウト待ちが回避される.
  • /**
     * @brief tOS    
     * @details
     * @author 01       http://01ketang.cc
     * @date 2017-06-01
     * @version 1.0
     * @copyright     ,        
     */
    #include "tinyOS.h"
    #include "app.h"
    #include "hal.h"
    
    static tTask task1;                     //   1  
    static tTask task2;                     //   2  
    static tTask task3;                     //   3  
    static tTask task4;                     //   4  
    
    static tTaskStack task1Env[TASK1_ENV_SIZE];     //   1     
    static tTaskStack task2Env[TASK2_ENV_SIZE];     //   2     
    static tTaskStack task3Env[TASK3_ENV_SIZE];     //   3     
    static tTaskStack task4Env[TASK4_ENV_SIZE];     //   4     
    
    int task1Flag;           //                
    int task2Flag;           //                
    int task3Flag;           //                
    int task4Flag;           //                
    
    static tMutex mutexA;
    static tMutex mutexB;
    
    /**
     *        
     * @param param         
     */
    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);        
        }
    }
    
    /**
     *        
     * @param param         
     */
    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);
        }
    }
    
    /**
     *        
     * @param param         
     */
    void task3Entry (void *param) {
        for (;;) {
            task3Flag = 1;
            tTaskDelay(1);
            task3Flag = 0;
            tTaskDelay(1);
        }
    }
    
    
    /**
     *        
     * @param param         
     */
    void task4Entry (void *param) {
        for (;;) {
            task4Flag = 1;
            tTaskDelay(1);
            task4Flag = 0;
            tTaskDelay(1);
        }
    }
    
    /**
     * App    
     */
    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));
    }
    
    
    
  • リソース申請順序の調整:ループ待ちを回避します.
  • /**
     * @brief tOS    
     * @details
     * @author 01       http://01ketang.cc
     * @date 2017-06-01
     * @version 1.0
     * @copyright     ,        
     */
    #include "tinyOS.h"
    #include "app.h"
    #include "hal.h"
    
    static tTask task1;                     //   1  
    static tTask task2;                     //   2  
    static tTask task3;                     //   3  
    static tTask task4;                     //   4  
    
    static tTaskStack task1Env[TASK1_ENV_SIZE];     //   1     
    static tTaskStack task2Env[TASK2_ENV_SIZE];     //   2     
    static tTaskStack task3Env[TASK3_ENV_SIZE];     //   3     
    static tTaskStack task4Env[TASK4_ENV_SIZE];     //   4     
    
    int task1Flag;           //                
    int task2Flag;           //                
    int task3Flag;           //                
    int task4Flag;           //                
    
    static tMutex mutexA;
    static tMutex mutexB;
    
    /**
     *        
     * @param param         
     */
    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);        
        }
    }
    
    /**
     *        
     * @param param         
     */
    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);
        }
    }
    
    /**
     *        
     * @param param         
     */
    void task3Entry (void *param) {
        for (;;) {
            task3Flag = 1;
            tTaskDelay(1);
            task3Flag = 0;
            tTaskDelay(1);
        }
    }
    
    
    /**
     *        
     * @param param         
     */
    void task4Entry (void *param) {
        for (;;) {
            task4Flag = 1;
            tTaskDelay(1);
            task4Flag = 0;
            tTaskDelay(1);
        }
    }
    
    /**
     * App    
     */
    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));
    }
    
    
    

    参考資料:
  • 手で組み込みオペレーティングシステム
  • の使い方を教えてあげます.