QNX RTOS:フロープランニング

QNXリアルタイムオペレーティングシステムに関する一連の注意事項の続き。 今回は、QNX6でのスレッドスケジューリングについて説明したいと思います* 。 読者シリーズの前の記事を読んだ読者)が既に知っているように、QNX6マイクロカーネルはプロセスではなくスレッドを制御します。 そして、次の瞬間に制御を受け取るべきスレッドのコンテキストをロードするのはマイクロカーネルです。 プロセッサによって実行される(つまり、プロセッサ時間を積極的に使用する)スレッドの選択は、スレッドのスケジューリングです。



スレッドのスケジューリングが発生したとき



QNX Neutrinoマイクロカーネルは継続的に動作しませんが、システムコール、例外、および割り込みの場合にのみ制御を受け取ります。 また、作業中の小核はフロー計画を実行します。 このことから、スケジューリングフローの操作はそれ自体ではなく、何らかのイベントによって発生するという正しい結論を下すことができます。 実際、そのようなイベントはほとんどありません。

計画に影響するフローパラメータ



QNX Neutrinoマイクロカーネルの主な機能の1つ( およびメッセージング後のおそらく最も重要な機能)は、スレッドスケジューリングです。 コンテキストを切り替えて、次の時点で実行するスレッドを選択するのはマイクロカーネルです。 マイクロカーネルは、これをすべて同様に行うのではなく、左ヒールの要求ではなく、次のフローパラメータに基づいて行います。

スレッドの優先順位は、スーパーユーザースレッド( rootとして実行)の場合は0〜255の範囲の数値であり、通常のユーザースレッドの場合は0〜63です。 ブートイメージを準備するときに、平均的なユーザーが利用できる優先順位の範囲を変更できます。 これを行うには、 procnto



-p



オプションを指定します。 ゼロ(最低)の優先度では、 idle



スレッドが実行され、システムにREADY状態でより高い優先度のスレッドがなくなると、常に制御が行われることに注意してください。



QNX6オペレーティングシステムは、 FIFO 、カルーセル(サイクリック、ラウンドロビン、RR)および散発的な**の複数のフロープランニングの分野をサポートしています。 このスレッド属性は、マイクロカーネルが同じ優先度レベルのスレッドから選択する必要がある場合にのみ考慮されます。 計画分野については後述します。



スイッチングフローの順序に影響する別の要因があります。 プロセッサを実行して使用する準備ができているすべてのスレッド(READY状態のスレッド)はキューに入れられます。 システムには256個のそのようなキューがあります(優先度の数による)。 すべてが等しく、マイクロカーネルが同じ優先度レベルを持つ2つのスレッドから選択する必要がある場合、キューの最初のスレッドが実行を開始します。 繰り返しますが、ストリームの混雑が優先されると、キューの最初に配置され、割り当て時に( sched_yield()



呼び出すことにより)、ストリームはキューの最後になります。



FIFO計画規律



フローにFIFOスケジューリング規則(先入れ先出し、先入れ先出し)が指定されている場合、必要な限り実行できます。 制御が別のスレッドに移るのは、スレッドが優先度の高いスレッドに取って代わられるか、ブロックされるか、自発的に制御を放棄する場合のみです。 この計画規律を使用すると、長時間の数学的計算を実行するスレッドはプロセッサを完全にキャプチャできます(つまり、同じ優先度と低い優先度のスレッドは許可されません)。



カルーセル訓練計画



この計画規律はFIFOに完全に似ていますが、スレッドが「際限なく」実行されず、特定のタイムスロット(タイムスライス)でのみ機能する点が異なります。 タイムクォンタムが終了すると、小核はプロセスを実行可能なスレッドのキューの最後に配置し、制御は次のスレッド(同じ優先度レベル)に転送されます。 この優先度レベルでREADY状態の他のスレッドが存在しない場合、別のスレッドにタイムスライスが割り当てられます。



操作のスケジューリングのカルーセル規則でスレッドに割り当てられる時間の量は、 sched_rr_get_interval()



関数を使用して決定できます。 実際、タイムスライスはticksizeのちょうど4倍です。 同様に、クロック間隔は、40MHz以上のプロセッサを搭載したシステムでは1ms、低速のプロセッサを搭載したシステムでは10msです*** 。 通常のx86コンピューターおよびラップトップでは、タイムクォンタムは4ミリ秒です。



散発的な計画規律



FIFOスケジューリングのように、散発的なスケジューリングが適用されるスレッドは、ブロックされるか、より高い優先度のスレッドに置き換えられるまで実行されます。 さらに、適応計画の場合と同様に、散発的な計画が適用されるフローの優先順位は低くなります。 ただし、散発的な計画では、フロー制御が大幅に正確になります。



散発的な計画では、スレッドの優先度は、フォアグラウンドの優先度(フォアグラウンド、通常の優先度)とバックグラウンド(低い)優先度の間で動的に変更できます。 この散発的な遷移を制御するには、次のパラメーターを使用します。

図からわかるように 図1 )、スレッドが準備完了状態になった瞬間からカウントされます。





図 1. フロー実行期間の補充は定期的に発生します



通常の優先度Nでは、スレッドは初期実行予算Cで設定された期間実行されます。この期間が終了すると、補充操作が発生するまでスレッドの優先度は低レベルLに下げられます。



たとえば、フローが決してブロックまたは中断されないシステムを想像してください-図 2。





図 2. スレッド優先度は、実行予算が補充されるまで低下します。



この場合、スレッドはより低い優先度(バックグラウンドモード)のレベルに移動し、その実行はシステム内の他のスレッドの優先度に依存します。



補充が発生するとすぐに、フローの優先度が初期レベルに上がります。 したがって、適切に構成されたシステムでは、スレッドは期間Cごとに最大時間C実行されます。これにより、優先度Nで実行されるすべてのスレッドがシステムリソースのC / Tパーセントのみを使用します。



スレッドが数回ブロックされると、異なる時点で複数の補充操作が発生する可能性があります。 これは、期間T内のフロー実行予算がCの値に達することを意味する場合があります。 ただし、この期間中、予算は継続的でない場合があります。





図 3. フロー優先度は、高と低の間で異なります



図 図3は、40ミリ秒の補充期間Tごとに、ストリームCの実行の予算が10ミリ秒であることを示しています。

  1. フローは3ミリ秒後にブロックされるため、3ミリ秒の補充操作は40ミリ秒で実行されるようにスケジュールされます。 その時点で、最初の補充期間の完了。
  2. フローの実行は6ミリ秒で再開し、この瞬間は次の補充期間Tの始まりを示します。フロー実行の予算にはまだ7ミリ秒のマージンがあります。
  3. フローはブロックせずに7ミリ秒間実行され、その結果、フロー実行バジェットが使い果たされ、フローの優先度がレベルLに低下します。レベルLでは、制御を取得できる、または取得できません。 46ミリ秒(40 + 6)に7ミリ秒の補充が計画されています。 期間Tの後
  4. 40ミリ秒で、フローバジェットが3ミリ秒補充されます(図のステップ1を参照)。その結果、フローの優先度は通常に上昇します。
  5. スレッドは予算の3ミリ秒を費やしてから、優先度の低い方に切り替えます。
  6. 46ミリ秒で、スレッドバジェットが7ミリ秒補充され(ステップ3を参照)、スレッドは再び通常の優先順位を受け取ります。
などなど。 したがって、2つの優先度レベル間を移動するストリームは、システム内の非周期的なイベントを予測可能かつ制御可能に処理します。



プログラムから計画の優先順位と規律を設定する方法



起動時の各スレッドは、親スレッドから優先順位と計画規律を継承します。 操作中に、スレッドはこれらの属性を変更する場合があります。 この目的のために、QNX6には次の機能があります。

POSIX呼び出し 説明
sched_getparam()



優先順位を取得します。
sched_setparam()



優先度を設定します。
sched_getscheduler()



計画の規律を取得します。
sched_setscheduler()



計画の規律を確立します。
プロセス全体ではなく、個別のスレッドを計画する優先順位と規律を取得または設定するには、関数SchedGet()



およびSchedSet()



使用できます。



ちょっとした管理



前回の投稿で、私はすでにpidin



コマンドについて言及しました。 今回は、QNXに固有の2つのチームに会います。 すべてのQNX6管理者は、これらのコマンドを知っており、使用できる必要があります。 そして、おそらく最も重要なコマンドはuse



です。



use



ユーティリティは、何らかの方法でman



コマンドに類似しています。 このユーティリティを使用すると、実行可能モジュール(バイナリ実行可能ファイル、スクリプト、または共有ライブラリ)に関するヘルプを取得できます。 use



の原則は、 man



use



多少異なりuse



すべてのヘルプ情報は、個別ではなく、実行可能モジュール自体に保存されます。 コマンドは、非常に単純に、たとえば次のように呼び出されます。



 # use sleep sleep - suspend execution for an interval (POSIX) sleep time Where: time is the number of seconds to sleep and can be a non-negative floating point number (0 <= time <= 4294967295).
      
      





ユーティリティユーティリティは、コマンドの操作に関する小さなヘルプを表示します;完全な説明はヘルプシステムで利用可能です。



すべての自尊心のあるQNX6管理者の武器にならなければならないもう1つの便利なコマンドはpidin



です。 このユーティリティは、実行スレッドやプロセスなど、システムに関するさまざまな種類の情報を提供します(この場合、ユーティリティはps



ユーティリティに似ています)。 たとえば、システムに関する一般情報を表示するには、次のコマンドを実行する必要があります。



 # pidin in CPU:X86 Release:6.5.0 FreeMem:166Mb/255Mb BootTime:Jul 05 15:53:27 MSKS 2011 Processes: 43, Threads: 107 Processor1: 131758 Pentium II Stepping 5 2593MHz FPU
      
      





パラメータなしでユーティリティを呼び出すと、すべてのプロセスとスレッドに関する情報が表示されます。 対象のプロセスに関する情報を取得するには、たとえば、 -P



スイッチを指定するだけです。



 # pidin -P io-audio pid tid name prio STATE Blocked 90127 1 sbin/io-audio 10o SIGWAITINFO 90127 2 sbin/io-audio 10o RECEIVE 1 90127 3 sbin/io-audio 10o RECEIVE 1 90127 4 sbin/io-audio 10o RECEIVE 1 90127 5 sbin/io-audio 50r INTR 90127 6 sbin/io-audio 50r RECEIVE 7
      
      





プロセスがメモリを使用する方法を確認するには、次のコマンドを実行します。



 # pidin -P io-audio mem pid tid name prio STATE code data stack 90127 1 sbin/io-audio 10o SIGWAITINFO 128K 112K 8192(516K)* 90127 2 sbin/io-audio 10o RECEIVE 128K 112K 4096(132K) 90127 3 sbin/io-audio 10o RECEIVE 128K 112K 8192(132K) 90127 4 sbin/io-audio 10o RECEIVE 128K 112K 4096(132K) 90127 5 sbin/io-audio 50r INTR 128K 112K 4096(132K) 90127 6 sbin/io-audio 50r RECEIVE 128K 112K 4096(132K) libc.so.3 @b0300000 472K 12K a-ctrl-audiopci.so @b8200000 12K 4096 deva-mixer-ac97.so @b8204000 24K 8192
      
      





使用されている共有ライブラリに関する情報も表示されます。 私の意見では、とても便利です。 pidin



ユーティリティは、多くのコマンドとオプションをサポートしています。 pidin



リストと説明は、QNXヘルプシステムにあります。



そして、最後ではあるが、価値ではなく、 slay



ユーティリティです。 ご想像のとおり、このコマンドはプロセスにシグナルを送信するために使用されます。 デフォルトでは、SIGTERMシグナルが送信され、通常はプロセスの終了につながります。 プロセスに送信する必要がある別のシグナルを指定できます。 この使用法では、 slay



killコマンドに似ていますが、最も興味深いことに、 slayコマンドはプロセス識別子(PID)だけでなく、プロセスの名前も受け入れます。 これは管理にも非常に便利です。 信号の送信に加えて、ユーティリティを使用して、プロセス計画の優先順位または規律を変更できます。 単一のストリームの特性を変更する場合は、 -T



スイッチを指定できます。 次のいくつかのコマンドは、3つのio-audio



プロセススレッドのスケジューリングの優先順位と規律を変更します。



 [22:47:33 root]# pidin -P io-audio pid tid name prio STATE Blocked 90127 1 sbin/io-audio 10o SIGWAITINFO 90127 2 sbin/io-audio 10o RECEIVE 1 90127 3 sbin/io-audio 10o RECEIVE 1 90127 4 sbin/io-audio 10o RECEIVE 1 90127 5 sbin/io-audio 50r INTR 90127 6 sbin/io-audio 50r RECEIVE 7 [22:47:36 root]# slay -T 3 -P 11r io-audio [22:47:38 root]# pidin -P io-audio pid tid name prio STATE Blocked 90127 1 sbin/io-audio 10o SIGWAITINFO 90127 2 sbin/io-audio 10o RECEIVE 1 90127 3 sbin/io-audio 11r RECEIVE 1 90127 4 sbin/io-audio 10o RECEIVE 1 90127 5 sbin/io-audio 50r INTR 90127 6 sbin/io-audio 50r RECEIVE 7
      
      





slay



ユーティリティの詳細な説明は、QNXヘルプシステムにあります。



念のため、QNX6にはおなじみのUNIX ps



kill



ユーティリティもあります。 ただし、QNX6を使用する方が、 pidin



pidin



よりもはるかに便利です。 システムの詳細を考慮します。



おわりに



この記事を読んだ後、QNX6のスレッドスケジューリングのアイデア、計画の優先順位と分野、システム機能とプロセスとスレッドを管理するためのユーティリティに関する十分な知識が得られました。 QNXには、興味深い技術であるアダプティブパーティショニング(適応分解)もあります。これにより、プロセスのグループを形成し、それらにCPU時間の割合を割り当てることができます。 すべてを統合しないために、この技術を次のメモのいずれかで説明します。



参照資料

  1. リアルタイムオペレーティングシステムQNX Neutrino 6.3。 システムアーキテクチャ。 ISBN 5-94157-827-X
  2. リアルタイムオペレーティングシステムQNX Neutrino 6.3。 ユーザーマニュアル。 ISBN 978-5-9775-0370-9
  3. Rob Krten、「QNX Neutrinoの紹介2.リアルタイムアプリケーション開発者向けガイド」、第2版。 ISBN 978-5-9775-0681-6


*この記事のQNX6はQNX 6.5.0を指します。 QNX Neutrinoカーネルは次のバージョンのいずれかで変更できるため、ここで説明するフロープランニングメカニズムは変更される可能性があります。



** QNX6には、ラウンドロビン(ラウンドロビン、RR、r)と同じ別の計画規律(OTHER、o)もあります。



***クロック間隔(ティックサイズ)は、たとえばClockPeriod()



関数を使用して変更できます。



All Articles