ロシアの1぀のRTOSの抂芁、パヌト6。ストリヌム同期ツヌル

残念ながら、実際のマルチスレッドアプリケヌションを開発する堎合、すべおのタスクのコヌドを蚘述し、それらをスケゞュヌラに接続し、単玔に起動するこずは䞍可胜です。



たずはバナリティヌから始めたしょう。タスクが倚い堎合、アむドルサむクルで実行するためにプロセッサヌ時間を無駄に䜿い始めたす。 以前の出版物ですでに述べたように、珟圚䜕の関係もない機噚からのデヌタが来なかった、たたは他の組織䞊の理由ですべおのタスクをブロックする必芁がありたす。 プロセッサクロックには垞にマむクロコントロヌラが搭茉されおいないため、実行するには、珟圚実行すべきタスクのみを蚭定する必芁がありたす。



さらに、特定のリ゜ヌス特に機噚でタスクが互いに競合する堎合がありたす。 マルチタスクの皮類を怜蚎する際に、SPIポヌトの競合の兞型的なケヌスを既に怜蚎したした協調マルチタスクに切り替えるこずで郚分的に解決されたしたが、垞に切り替えるこずはできたせん。



そしお最悪の堎合はタスクの䟝存関係です。 倚くの堎合、1぀のタスクの結果は別のタスクで䜿甚されたす。 明らかな䟋ずしお、次のものを挙げるこずができたす枩床センサヌからの十分なデヌタを受信しお​​平均化するたで、枩床コントロヌラヌのPID出力のデヌタを再蚈算するこずは無意味です。終端文字行終端蚘号が受信されるたで端末から。 そしお、明癜なものに加えお、䟝存症ずそれらが生成する人皮の倚くの明癜でないケヌスがありたす。 初心者の開発者は、プログラムのアルゎリズムを盎接実装するよりも、レヌスず戊うのに時間がかかる堎合がありたす。



これらすべおの堎合においお、同期オブゞェクトは開発者の助けになりたす。 珟圚の出版物で、MAX MAX RTOSで䜿甚可胜な同期オブゞェクトず関数を考えおみたしょう。



前の郚分を芋たこずがない人のために、リンク



パヌト1.䞀般情報

パヌト2. RTOS MAXのカヌネル

パヌト3.最も単玔なプログラムの構造

パヌト4.有甚な理論

パヌト5.最初のアプリケヌション

パヌト6.スレッド同期ツヌルこの蚘事

パヌト7.タスク間でデヌタを亀換する手段

パヌト8.割り蟌みの凊理



クリティカルセクション



りォヌムアップするには、CriticalSectionクラスを怜蚎したす。 コンテキストの切り替えが受け入れられない領域をフレヌム化するために䜿甚されたす。



クラスオブゞェクトがスコヌプに衚瀺されるずすぐに、優先床がMAX_SYSCALL_INTERRUPT_PRIORITY以䞋のすべおの割り蟌みがブロックされたす。 珟圚、この定数は5であり、デバむスおよびシステムタむマヌからのすべおの割り蟌みをブロックしたすが、䟋倖的な状況をブロックしたせん。



オブゞェクトがスコヌプから倖れるず、割り蟌みレベルは入力前の状態に戻りたす。 埌者では、ネストされたクリティカルセクションの取埗を心配する必芁はありたせん。実際に機胜するのは最初のセクションのみです。 倖郚以倖はすべお䞍必芁な䜜業を行いたす。 たず、蚱可された高レベルの割り蟌みを同じ割り蟌みに眮き換え、終了するずきに元の割り蟌みを埩元するず、元の高のたたになりたす。 埋め蟌たれたクリティカルセクションの最も倖偎を終了するず、䜎レベルが埩元されたす。 もちろん、ネストは関数が呌び出されたずきに最も頻繁に取埗されたす。この関数にはクリティカルセクションもありたす。



クリティカルセクションは割り蟌み優先床を倉曎する、぀たりNVICをプログラムするため、特暩モヌドコヌドでのみ䜿甚する必芁がありたす。



䟋に぀いお考えおみたしょうピンク色で匷調衚瀺された領域は、クリティカルセクションによっお保護されおいたす。ここでは、コントロヌルがタスクから削陀されないこずが保蚌されおいたす







同じこず-テキスト
void ProfEye::Tune() { ProfData::m_empty_call_overhead = 0; ProfData::m_empty_constr_overhead = 0; ProfData::m_embrace_overhead = 0; CriticalSection _cs_; loop ( int, i, 1000 ) { PROF_DECL(PE_EMPTY_CALL, empty_call); PROF_START(empty_call); PROF_STOP(empty_call); { PROF_EYE(PE_EMBRACE, _embrace_); { PROF_EYE(PE_EMPTY_CONSTR, _empty_constr_); } } } ProfData::m_empty_call_overhead = prof_data[PE_EMPTY_CALL].TimeAvg(); ProfData::m_empty_constr_overhead = prof_data[PE_EMPTY_CONSTR].TimeAvg(); ProfData::m_embrace_overhead = prof_data[PE_EMBRACE].TimeAvg() + ProfData::ADJUSTMENT - 2 * ProfData::m_empty_constr_overhead; }
      
      







もちろん、オブゞェクトのスコヌプは垞に䞭括匧で制限できたす。







テキスト
 ProfEye::ProfEye(PROF_EYE eye, bool run) { m_eye = eye; m_lost = 0; m_run = false; if ( run ) { { CriticalSection _cs_; prof_data[m_eye].Lock(true); m_up_eye = m_cur_eye; m_cur_eye = this; } Start(); } else m_up_eye = nullptr; }
      
      







クリティカルセクションには䜕を含める必芁がありたすか たずえば、たずえば、いく぀かの倉数をアトミックに倉曎する必芁がある操䜜䞊蚘の䟋はたさにそれを行いたす。 1぀のタスクが読み取り、他のタスクが曞き蟌みを行うさたざたなリストやその他のものには、アトミックアクセスが必芁になる堎合がありたす。



しかし、それほど明癜なものはありたせん。 あるタスクで増加し、別のタスクで枛少する特定のカりンタヌがあるずしたす。 それは非垞にアトミックな操䜜のようです



cnt ++;



しかし、高レベル蚀語のレベルではアトミックです。 アセンブラレベルでは、読み取り-倉曎-曞き蟌み操䜜に分割されたす。



26: cnt++;

0x08004818 6B60 LDR r0,[r4,#0x34]

0x0800481A 1C40 ADDS r0,r0,#1

0x0800481C 6360 STR r0,[r4,#0x34]







倀忠実床、たずえば10が既にレゞスタr0に入力された埌、スケゞュヌラが制埡を別のタスクに転送するずしたす。 たた、10の倀をカりントし、9を入力しお倀を枛らしたす。次に、制埡が珟圚のタスクに戻ったずきに、倉数ではなく、レゞスタヌr0にあるものに10を远加したす。 11になりたす。カりンタヌの倀が歪んでいたす。



それはそのような状況から保護するためだけであり、クリティカルセクションは非垞に適しおいたす。



 { CriticalSection cs; cnt++ }
      
      





もちろん、NVICを䜿甚するオヌバヌヘッドも念頭に眮いおおく必芁がありたす。3぀ではなく、はるかに倚くのアセンブラヌコマンドになるためです。



27: CriticalSection cs;

0x0800481A 4668 MOV r0,sp

0x0800481C F7FEFCE8 BL.W _ZN4maks15CriticalSectionC2Ev (0x080031F0)

28: cnt++;

0x08004820 6B60 LDR r0,[r4,#0x34]

0x08004822 1C40 ADDS r0,r0,#1

29: }

0x08004824 6360 STR r0,[r4,#0x34]

0x08004826 4668 MOV r0,sp

0x08004828 F7FEFDA0 BL.W _ZN4maks19InterruptMaskSetterD2Ev (0x0800336C)







これはシステムサブルヌチンの内容をカりントするものではありたせん...読者がその耇雑さを想像できるように、ここに最初の1぀だけを瀺したす。



0x080031F0 B510 PUSH {r4,lr}

0x080031F2 2150 MOVS r1,#0x50

0x080031F4 F000F8AE BL.W _ZN4maks19InterruptMaskSetterC2Ej (0x08003354)

0x080031F8 4901 LDR r1,[pc,#4] ; @0x08003200

0x080031FA 6001 STR r1,[r0,#0x00]

0x080031FC BD10 POP {r4,pc}







あなたが芋るこずができるように-これはただ最倧のネストではありたせん...䞀方、それはただ悪の少ないです。 頻繁に出入りするクリティカルセクションに倢䞭にならないでください。



クリティカルセクションは非垞に匷力ですが、朜圚的に危険なツヌルです。スコヌプから倖れるたでマルチタスクがオフになるためです。 理想的には、数行のみをロックする必芁がありたす。 サむクルの存圚は、遅延時間を倧幅に増加させ、関数を入力したす-さらにはプログラマヌがこれらの関数に費やされた時間を十分に認識しおいない堎合さらに、ある皮の機噚で䜜業するこずは非垞に朜圚的に危険なこずです。 プログラマに、呚波数10 MHzのSPIバスでの2バむトの送信䞭にコンテキストスむッチがないこずを保蚌するこずを決定させたす。 1ビットの呚期は100 nsです。 16ビット-1.6ÎŒs これは完党に受け入れられる結果です。 次のタスクで倱われるのはこのセクションだけです䞀般的に、これはスケゞュヌラヌの時間に匹敵したす。 しかし、250キロビット/秒の速床で20文字のUART文字列を介しお送信する堎合、20 * 10 * 4ÎŒs= 0.8ミリ秒かかりたす。 ぀たり、タスクタむムクォンタムの終わり近くでプロセスを開始するず、次のタスクのクォンタム党䜓のほずんどを「食べる」こずになりたす。



䞀般に、クリティカルセクションのメカニズムは非垞に匷力ですが、それを䜿甚するプログラマヌは、リアルタむムでシステムの動䜜を保蚌するすべおの責任を負いたす。



繰り返したすが、他のリ゜ヌスを埅機しおいる機胜を䜿甚しお、クリティカルセクションにあるタスクを安楜死させないでください。



最も単玔な䟋を考えおみたしょう。 ポヌトの状態を倉曎する既知のタスクで、ロック付きの遅延関数を定期的に呌び出したす。



  virtual void Execute() { while (true) { GPIOE->BSRR = (1<<nBit); Delay (5); GPIOE->BSRR = (1<<(nBit+16)); Delay (5); } }
      
      





通垞の蛇行を䞎えたす







クリティカルセクションを远加







テキスト
  virtual void Execute() { CriticalSection cs; while (true) { GPIOE->BSRR = (1<<nBit); Delay (5); GPIOE->BSRR = (1<<(nBit+16)); Delay (5); } }
      
      







たったく異なる信号を受け取りたす







ズヌムむン-信号呚期が完党に間違っおいたす...







䞀般に、クリティカルセクションは匷力なツヌルですが、アクションたたは少なくずも、実行するすべおのステップを制埡するを認識しおいる堎合にのみ䜿甚しおください。



りォヌムアップは䜕ずか匕きずられたした。 最も単玔なものは、たくさんのシヌトに広がっおいたす。 さお、ロゞックがもう少し耇雑になりたしたが、必芁なテキストは少なくなりたした。バむナリセマフォです。



バむナリセマフォ



むかしむかし、鉄道ではセマフォが積極的に䜿甚されおいたした。 圌らには2぀の州がありたした䞊げられた-列車は動くこずができたす。 停止-列車は埅たなければなりたせん。 たあ、ディスパッチャはそれを䞊げ䞋げしたした。 そしお、ここでは、いく぀かのタスク耇数のタスクがロヌプを匕っ匵っおディスパッチャずしお動䜜、いく぀かのタスク耇数のタスクがパスが開かれるのを埅ちたす。 同時に、保留䞭のタスクはブロックされたす。぀たり、時間を浪費したせん。







このようなセマフォは、BinarySemaphoreクラスによっお実装されたす。



クラスコンストラクタヌには、セマフォの初期状態を蚭定する必須匕数が含たれおいたす



明瀺的なBinarySemaphorebool is_empty = true



さらに、バむナリセマフォの機胜のみを怜蚎したす事実は、それが単玔なセマフォの盞続人であり、以䞋でその機胜をすべお怜蚎するこずです。



セマフォを通過するタスクは、 Wait関数を呌び出す必芁がありたす。 この関数の匕数はミリ秒単䜍のタむムアりトです。 指定した時間内にタスクのロックが解陀された堎合、関数はResultOkを返したす 。 したがっお、タむムアりトが発生した堎合 、関数の結果はResultTimeoutになりたす。 関数が「停止する」たで埅機する必芁がある堎合、 INFINITE_TIMEOUTに等しいタむムアりト倀を枡す必芁がありたす。



関数がれロのタむムアりト倀で呌び出されるず、即座に制埡を返したすが、結果 ResultOkたたはResultTimeout  からセマフォが開いおいるか閉じおいるかは明らかです。



割り蟌みから呌び出された堎合、タスクのブロックは䞍可胜であるため、れロ以倖のタむムアりトでは、関数の結果はResultErrorInterruptNotSupportedになりたす。 ただし、タむムアりトがれロの堎合、関数は割り蟌みから呌び出すこずもできたす。



関数がResultOkの結果を返す堎合、セマフォは自動的に閉じたす。



既に述べたように、いく぀かのタスクはセマフォを䞀床に埅぀こずができたす。 この堎合、最初に芋萜ずされる「ラッキヌなもの」の遞択は、次のように実行されたす。埅機リスト内のタスクは、優先順䜍の降順で、同じ優先順䜍で、 Wait関数を呌び出した順番になりたす。



セマフォを開くには、 Signal関数が䜿甚されたす。 セマフォがすでに開いおいる堎合は、 ResultErrorInvalidStateの結果を返したす。それ以倖の堎合は-ResultOkを 返したす。 MAX_SYSCALL_INTERRUPT_PRIORITYよりも高い優先床を持぀割り蟌みから関数を呌び出すこずはできたせん。



セマフォ



正盎なずころ、私はこの名前が嫌いです。 この同期オブゞェクトを「Zavkhoz」ず呌ぶ方が正しいでしょうが、䌝統に反論するこずはできたせん。 セマフォず呌ばれるすべおの堎所で、RTOS MAXも䟋倖ではありたせん。 単玔なセマフォたたはサプラむマネヌゞャずバむナリセマフォの違いは、カりントリ゜ヌスをりェアハりスに入れるできるこずです。 少なくずも1぀のリ゜ヌスがありたす-タスクはパスできたすリ゜ヌスの数は枛少したす。 リ゜ヌスなし-タスクは少なくずも1぀が衚瀺されるたで埅機したす。







このようなセマフォは、リ゜ヌスを割り圓おる必芁があるずきに圹立ちたす。 たずえば、USBにデヌタを出力するために4぀のバッファを開始したしたこのバスはバむトでは動䜜したせんが、バむトの配列で動䜜するため、バッファにデヌタを準備するのが最も䟿利です。 したがっお、䜜業タスクは空きバッファヌがあるかどうかを刀別できたす。 ある堎合は、蚘入しおください。 いいえ-USBで動䜜するものが少なくずも1぀を送信しおリリヌスするたで埅ちたす。 䞀般に、1぀ではなく耇数のリ゜ヌスがどこかに割り圓おられおいる堎合、それらの配垃をサプラむマネヌゞャたたは、埓来の呜名法ではセマフォに割り圓おるのが最も䟿利です。



したがっお、このオブゞェクトはSemaphoreクラスで実装されたす。 バむナリセマフォずの違いを考慮しおください。 たず、圌はわずかに異なるコンストラクタを持っおいたす



セマフォsize_t start_count、size_t max_count



最初のパラメヌタヌは、最初にボックスに入れるものの数、2番目のパラメヌタヌ-このボックスの寞法です。 䜜業の開始時にリ゜ヌスの完党な䞍足を宣蚀し、それらを远加するこずは䟿利です思い出すように、 Signal関数を呌び出したす。 堎合によっおは、逆に、初期リ゜ヌスが最倧にロヌドされおから䜿甚されるこずもありたす。 ブヌトストラップが䞍完党な他のオプションも可胜ですが、読者は必芁なずきにこれを思い付くでしょう。



Signal関数は、それぞれリ゜ヌスカりンタヌを増やしたす。 最倧倀に達するず、 ResultErrorInvalidStateを返したす。 繰り返しになりたすが、MAX_SYSCALL_INTERRUPT_PRIORITYより高い優先床の割り蟌みから関数を呌び出すこずはできたせん。



リ゜ヌスの数がれロに等しくない堎合、カりンタヌを枛らしながら、 Wait関数はタスクをスキップしたす。 リ゜ヌスがない堎合、タスクはSignal関数を介しお返されるたでブロックされたす。 繰り返したすが、割り蟌みからこの関数はタむムアりトなしでしか呌び出せないこずを思い出しおください。



次に、バむナリの堎合に意味をなさない関数を考えたす。



GetCurrentCountは、リ゜ヌスカりンタヌの珟圚の倀を返したす



GetMaxCountは、可胜な最倧カりンタヌ倀を返したすセマフォヌが別のタスクを䜜成した堎合-その特性を刀別するのに圹立぀堎合がありたす



ミュヌテックス



このオブゞェクトの名前は、「盞互排他的」ずいう蚀葉に由来しおいたす。 ぀たり、システムは1぀のリ゜ヌスぞの盞互排他的アクセスを提䟛したす。 セマフォでいく぀かのタスクが解決を埅っおいお、他のタスクがセマフォを開いおいる堎合、この堎合、誰もがリ゜ヌスをキャプチャしようずしたすが、システム自䜓がそれを提䟛したす。



簡単に蚀えば、ミュヌテックスの本質は「最初に起きたのは誰ですか-それずスリッパ」ずいうフレヌズで説明できたす。 保護されたオブゞェクト-「スリッパ」がありたす。 倫は目を芚たし、圌らに尋ねたした-システムは、それらを分割されおいない䜿甚のために圌に䞎えたした。 劻ず息子が尋ねた-圌らはブロックされたした。 倫がシステムにスリッパを返すずすぐに、劻はそれらを受け取りたした。 圌女は戻った-息子を受け取った。 圌は戻りたした-オブゞェクトはフリヌ状態になり、次のリク゚スタヌは埅機せずに再びそれらを受け取りたす。



マむクロコントロヌラでは、この方法で保護する必芁のある玠晎らしいリ゜ヌスは、いく぀かのタスクがポヌトを介しお機胜しようずしおいる堎合、ポヌトSPI、I2Cなどです。 いく぀かの異機皮デバむスを同じ物理チャンネルに接続できるこずをすでに怜蚎しおいたす。たずえば、クラシックテレビでは、1぀のI2Cバスにビデオプロセッサ、オヌディオプロセッサ、テレテキストプロセッサ、チュヌナヌが存圚する可胜性がありたす-それらは異なるタスクによっお凊理される可胜性がありたす。 なぜBSYビットのリセットを埅぀ためにCPU時間を浪費するのですか さらに、ずにかく、衝突が可胜です。 BSYポヌトのビットを排他的に分析し、それらを段階的に実行する3぀のタスクの䜜業を怜蚎したす。







ご芧のずおり、ステップ7では、2぀のタスクがすぐにバスを制埡しようずしおいたす。 ミュヌテックスで保護されおいれば、これは起こりたせんでした。 さらに、条件付きステップ1実際、これはタスク2たたはタスク3のいずれかがブロックされる倧量のステップですで、タスクは時間を浪費しおいたした。 Mutexはこの問題も解決したす-埅機䞭のタスクはすべおブロックされたす。



開発者がミュヌテックスに倢䞭になりすぎお、タスクがミュヌテックスを数回キャプチャするこずがある堎合がありたす。 もちろん、ほずんどの堎合、これはネストされた関数で発生したす。 関数1はミュヌテックスをキャプチャし、制埡は関数2から関数3に、そこから関数41幎前に蚘述に枡され、同じミュヌテックスをキャプチャしようずしたす。 このような堎合、ブロッキングを回避するために、再垰的なmutexを䜜成する必芁がありたす。 1぀のタスクでそれらを繰り返しキャプチャできたす。 圌が捕らえられた回数だけ解攟するこずが重芁です。 Windows OSでは、すべおのミュヌテックスは再垰的ですが、匱いマむクロコントロヌラヌに察するこのようなアプロヌチは、リ゜ヌスの䞍圓な支出に぀ながるため、デフォルトでは、ミュヌテックスはMAX MAX RTOSで再垰的ではありたせん。



Mutexクラスの䞻な機胜を怜蚎しおください。 たず、そのコンストラクタ



ミュヌテックスboolrecursive = false;



コンストラクタヌ匕数は、タむプを決定したす-再垰的かどうか。



Lock関数はミュヌテックスをキャプチャしたす。 タむムアりト倀は匕数ずしお枡されたす。 い぀ものように、特別な倀を蚭定できたす-れロタむムアりト埅機せずに即時出力たたはINFINITE_TIMEOUT 勝利たで埅機。 ミュヌテックスがキャプチャできた堎合、ResultOkが返されたす。 タむムアりトが経過するず、結果ResultTimeoutが返されたす。 非再垰的なミュヌテックスをキャプチャしようずするず、結果はResultErrorInvalidStateになりたす。 ミュヌテックスは割り蟌みでキャプチャできたせん。 これを行おうずするず、結果はResultErrorInterruptNotSupportedになりたす。



ロック解陀関数-ミュヌテックスを解攟したす。 したがっお、保護されたセクションの実行の最埌に呌び出す必芁がありたす。



IsLocked関数を䜿甚するず、ミュヌテックスをキャプチャするか、キャプチャせずに解攟するかを決定できたす。 プリ゚ンプティブマルチタスクでは、結果は分析される前でも関連性を倱う可胜性がありたすが、協調マルチタスクでは、この機胜が圹立぀堎合がありたす。



今、優先床の継承などに぀いお話す䟡倀がありたす。 システムに通垞の優先床を持぀タスクA、高優先床を持぀B、および高優先床を持぀Cがあるずしたす。 タスクBずCがブロックされ、Aがこの時点でミュヌテックスをキャプチャできたずしたす。 それをグラフィカルに描画しお、タスクを互いの䞊に配眮したす優先床が高いほど、図のタスクが高くなりたす







これで、タスクCのロックが解陀されたした。 もちろん、最高の優先順䜍を持ち、それが実珟し始めたした。 そしお、圌女も同じミュヌテックスをキャプチャするずしたす。







しかし、ミュヌテックスはタスクAを所有しおいたす 通垞のロゞックでは、ビゞヌになるず、タスクCは解攟されるたでブロックされたす。 そしお突然、タスクBのロックが解陀されたした他のリ゜ヌスを埅機させ、解攟されたした。 その優先床はAの優先床よりも高いため、正確に実行されたす぀たり、タスクB







䜕がありたすか 優先床の高いタスクCは、ミュヌテックスが解攟されるのを埅っおいるため実行できたせん。 しかし、珟圚の所有者は、mutexの所有者よりも優先床の高いタスクに取っお代わられたすが、優先床は䜎く、比范的䞍公平にブロックされたタスクであるため、埅機できたせん。



これを防ぐために、所有暩の時点でミュヌテックスの所有者には、珟圚圌を埅っおいるタスクの最高タスクの優先床が割り圓おられたす。 このようなメカニズム優先床継承により、ミュヌテックスが解攟される瞬間を抂算できたす。







優先床の継承䞭にタスクAが通垞の優先床を持぀タスクEずも盞互䜜甚するず、この盞互䜜甚が倱われるため、この事実は非垞に重芁です。 残念ながら、これでは䜕もできたせんRTOSの暙準コンセプトのフレヌムワヌク内で。これは、プログラムを蚭蚈するずきに単玔に考慮されるべきです。



ミュヌテックスガヌド



叀兞的なアルゎリズムプログラミングには、任意のアルゎリズムで1぀の入力ず1぀の出力が含たれたす。 しかし、この原則の狂信的な芏定は、テキストの䞍圓な耇雑化ず読みやすさの䜎䞋に぀ながるような実践です。 次の擬䌌コヌドを芋おみたしょう。



 m_mutex.Lock(); switch (cond) { case 0x00: .... return ResultCode1; case 0x02: .... return ResultCode2; case 0x0a: .... return ResultCode3; case 0x15: .... return ResultCode4; } .... m_mutex.Unlock();
      
      





実際、ここで関数を終了する前に、mutex.Unlockを䜓系的に配眮する必芁がありたす。 たた、倧芏暡なアルゎリズムには、このようなセクションが倚数存圚する堎合がありたす。 そしお、それらを远加できたす。 遅かれ早かれ、プログラマはミュヌテックスをどこかでロック解陀するこずを忘れ、プログラムはフリヌズしたす。 そしおこれは、人類が倜眠れなかったずいう事実にもかかわらず、䞀般にPLOを発明し、特にクラスのデストラクタを発明したした



ミュヌテックスガヌドは、デストラクタが䜿甚するこずだけを行いたす。 むンタヌフェヌス郚分のこのクラスには、コンストラクタヌしかありたせん。 プログラマヌガむドからその説明をコピヌしたす。

明瀺的なMutexGuardMutexずmutex、bool only_unlock = false;



匕数





ミュヌテックスはコンストラクタに枡される必芁がありたす。 圌は捕らえられたす。 そしお、ミュヌテックスガヌドが芖界から離れた瞬間に圌は解攟されたす。 したがっお、前の䟋は次のように曞き換える必芁がありたす。





テキスト
  { MutexGuard (m_mutex); switch (cond) { case 0x00: .... return ResultCode1; case 0x02: .... return ResultCode2; case 0x0a: .... return ResultCode3; case 0x15: .... return ResultCode4; } .... }
      
      







むベント



セマフォずミュヌテックスは通垞、特定のリ゜ヌスを䜿甚するずきにタスクの競合を排陀するために䜿甚されたすが、ロックを解陀する条件ができるたでタスクをブロックする必芁がある堎合がありたす。 兞型的なシナリオ-割り蟌みが発生し、ハンドラヌ関数が遅延凊理の優先床の高いタスクに信号を送り、䜕らかのタスクを実行する必芁があるこずを通知したす。 むベントを䜿甚するず、このメカニズムを実装できたす。



前の段萜を読んだ埌、むベントは単にセマフォを耇補しおいるように芋えるかもしれたせん。 しかし、これはそうではありたせん。 違いを芋おみたしょう。



最初の違いむベントは、それを埅っおいる人にのみ圱響したす。 珟時点でむベントに受信者がいない堎合、どこにも行きたせん。 むベントの発生埌すぐに、誰かがそれを埅ち始めたす-それはブロックされたす。 ロック解陀は、次のむベントでのみ発生したす。 誰も時間がなかった-圌は遅れおいた。 私たちが思い出すように、セマフォは、反察に、誰かがそれを埅っおいたかどうかにかかわらず、ずにかく開きたす。 そしお、セマフォを最初に枡すものはスキップされたす。



2番目の違いは、耇数のタスクがセマフォのオヌプンを埅機しおいる堎合、そのうちの1぀だけがロック解陀されたす。 残りは次のオヌプンを埅ちたす。 むベントは、その発生を埅機しおいた党員のロックを解陀するずきにモヌドに蚭定できたす。 ぀たり、埅機䞭のすべおのタスクは「ブロック」状態から「アクティブ」状態の誰かに転送され、最も幞運なタスクは「実行䞭」状態に転送されたす。



残り-むベントのロゞックは、バむナリセマフォのロゞックに䌌おいたす。



クラスコンストラクタヌ



むベントbool broadcast = true;



ブロヌドキャストパラメヌタは、むベントの通知を埅っおいる受信者に通知するルヌルを蚭定したす。 true –それを埅っおいるすべおのタスクがロック解陀され、false – 1぀のタスクのみがロック解陀されたす。これは、このむベントを埅っおいるキュヌの最初のタスクです。



Raise関数はむベントをディスパッチしたす。 MAX_SYSCALL_INTERRUPT_PRIORITYよりも高い優先床を持぀割り蟌みから呌び出すこずはできたせん。



Wait関数は、以前に怜蚎された同期オブゞェクトず同じ名前の関数によっおすでによく知られおいたす。たた、タむムアりト匕数がありたす。同様に、タむムアりトはれロたたはINFINITE_TIMEOUTにできたす。この関数は、割り蟌みから呌び出すこずはできたせん。



同期オブゞェクトの䜿甚䟋



残念ながら、同期オブゞェクトが䜿甚される単玔で矎しい䟋を䜜るこずは䞍可胜です。シンプルなものはすべお、関数呌び出しの䟋のデモンストレヌションになりたす。実際に適甚できるものは、あたりにも倚くのボリュヌムを占有したす。それらを説明するには長い時間がかかり、読者は2ペヌゞ目のスレッドを倱い、他の28のペヌゞは誰にも読たれたせん。したがっお、そのような䜜品を曞くこずは控えたす。



蚈画された第3郚では、CNCマシン甚の倧芏暡プログラムの適応の説明が衚瀺されたす。そのための䟋を残したす。そしお、緎習を切望する人には、OSの単䜓テストをお勧めできたす。これらは、ディレクトリ... \ maksRTOS \ Source \ Tests \ Unit testsにありたす。ホストされおいるディレクトリのリストは次のずおりです



。BinarySemaphore

Event

MessageQueue

Mutex

MutexGuard

スケゞュヌラ

セマフォ




ベストプラクティスの䟋は思い぀きにくいです。あなたの研究を楜しんでくださいただし、たれな読者はテストの第1四半期の終わりに到達するずの意芋がありたす。



All Articles