FreeRTOS:ミューテックスとクリティカルセクション



こんにちは。 これは、FreeRTOSマルチスレッド環境に関する最後の記事です。ここでは、ミューテックスとクリティカルセクションについて説明します。

前の部分へのリンク:





ミューテックス。



リソース(ポート、メモリ領域、変数)への共有アクセスが必要な状況を考えてみてください。また、単位時間内に1つのタスクのみがこのリソースにアクセスでき、残りのタスクはアクセスしたい場合です。リソースは並んで待機する必要があります。

特別なタイプのセマフォが助けになります-ミューテックス(ミューテックス)。 この抽象化は一種のトークンであり、タスクはリソースにアクセスでき、リソースの処理の最後に返す必要があり、それを取得したタスクのみが「トークン」を返すことができます。

次の図は、このロジックを示しています。







図1 最初の状況は、リソースにアクセスしたい3つのタスクです。







図2 タスクB-「トークン」(ミューテックス)を取りました。







図3 タスクBはリソースにアクセスし、必要なアクションを実行します。







図4 タスクが完了すると、タスクBはトークンを返し、その結果、他のタスクがリソースにアクセスできるようになります。

ミューテックスを作成するには、特別なAPI関数が使用されます。

xSemaphoreHandle xSemaphoreCreateMutex( void );
      
      





作成されたミューテックスを返します。十分なメモリがない場合はNULLを返します。

次のコードは、ミューテックスを操作するメカニズムを示しています。

  if( xSemaphoreTake( xMutex, portMAX_DELAY ) == pdTRUE ) { //      . //  "". xSemaphoreGive( xMutex ); }
      
      





重要なセクション。



コードのロジックの過程で、コードの短いセクションが必要な場合、その実行は別のタスクへの切り替えによって中断されるべきではありません(そのようなセクションの例は、ポートへの値の記録です)。 このため、FreeRTOSは特別なマクロを使用します。

 taskENTER_CRITICAL(); { //    ,      . } taskEXIT_CRITICAL();
      
      





このセクションのコードの実行中、コンテキストは切り替えられません(つまり、別のタスクに切り替えられます)が、ネストされた割り込みをサポートするFreeRTOSのバージョンで割り込みが発生する可能性がありますが、すべてではなく、 configMAX_SYSCALL_INTERRUPT_PRIORITY定数よりも高い優先度を持つ割り込みのみが発生します。



クリティカルセクションを構築する別のアプローチは、スケジューラを一時停止することです。 唯一の違いは、マクロで構築されたクリティカルセクションが他のタスクと割り込みの共有からコードの実行セクションを保護することと、スケジューラの中断で構築されたクリティカルセクションが他のタスクからのみ保護されることです。

これを行うには、2つのAPI関数を使用します。

 void vTaskSuspendAll(); { //   . } portBASE_TYPE xTaskResumeAll();
      
      





この場合、関数xTaskResumeAll()によって返される値 taskYIELD()を使用して強制コンテキスト切り替えを実行する必要があることを示します。



優先順位と行き止まりの逆転。



前の記事で、優先順位を逆転させてタスクを行き止まりにする問題の解決策として、ゲートキーパータスクをさりげなく言及しました。 ここで、それが何であるかをより詳細に説明したいと思います。



優先順位の反転とは、 タスクBよりも優先度の高いタスクAタスクの完了を期待する状況です。 彼はトークン(mutex)をキャプチャした最初の人物でした。



デッドロック -2つのタスクが互いに待機している状況 それぞれが他方に「トークン」を与える必要があります。 例:

  1. タスクAが実行され、「カウンター」Xをキャプチャします。
  2. タスクAの実行は、タスクBによって中断されます。
  3. タスクBは、現在「タスク」Aで使用されている「カウンター」Xをキャプチャしようとする前に、「カウンター」Yをキャプチャします。その結果、タスクBはタスクAの期待に落ちます。
  4. タスクAは実行を継続し、タスクBが使用する「トークン」Yをキャプチャしたいため、結果として待機状態になります。


「行き止まり」を回避するには、すべてのタスクが特定の順序で「トークン」を取得する必要があります。たとえば、タスクAが最初で、次にBなどです。



おそらくそれだけです。今後、記事を調整して参照するために、サイクル全体で修正を聞くのは興味深いでしょう。

さらなる研究のために、最初にオリジナルのマニュアル「FreeRTOSリアルタイムカーネルの使用」、記事の執筆に使用された情報、および公式Webサイトのドキュメントを読むことをお勧めします。



All Articles