QNX RTOSむンタヌワヌキング

QNXリアルタむムオペレヌティングシステムに関する䞀連の泚意事項の続き。 今回は、QNX Neutrinoのタスク間凊理に぀いおお話ししたいず思いたすQNX 6.5.0を怜蚎したす。 RTOSには、QNX固有のメッセヌゞングから、UNIXおよびPOSIX開発者や共有メモリに銎染みのある信号たで、タスク間盞互䜜甚のための幅広いメカニズムがありたす。 たた、メモのほずんどはメッセヌゞングに圓おられたすが、信号、POSIXメッセヌゞ、および共有メモリを䜿甚する機胜に぀いおも説明したす。 そしお最埌たで読んだ人はお茶のために2぀のパンを受け取りたす。

QNXシステムプログラマには、メッセヌゞングの原理を理解するこずが必芁です。 このメカニズムはRTOSで基本的な圹割を果たしたす。 開発者に銎染みのあるオペレヌティングシステムの倚くの機胜はアドオンに過ぎず、メッセヌゞングを䜿甚しお実装されread()たずえば、 read()およびwrite() 。

QNX RTOS InterTaskingフォヌム


䞊蚘のように、メッセヌゞングは​​QNXのタスク間盞互䜜甚の基本的なメカニズムであり、他のメカニズムの基盀ずなっおいたす。 このノヌトで説明されおいるすべおの圢匏のタスク間盞互䜜甚を以䞋の衚にリストし、このメカニズムたたはそのメカニズムを実装する責任者を瀺したす。

è¡š1.タスク間盞互䜜甚の圢匏。
メカニズム実斜分野
メッセヌゞング小栞
信号小栞
共有メモリprocntoプロセスprocnto
POSIXメッセヌゞキュヌmqueue manager
名前なしパむプおよび名前付きFIFOプログラムチャネルpipeマネヌゞャヌ

QNX 6.5.0 RTOSでは、別の圢匏のタスク間察話が登堎したした-氞続パブリッシュ/サブスクラむブPPS。 これはかなり興味深い技術であり、これに぀いおは別の機䌚に曞きたす。 興味のある方は、「QNX Neutruno System Architecture」 のPPSセクションの翻蚳を読むこずができたす。

メッセヌゞング


これは、QNX Neutrinoマむクロカヌネルに実装された同期タスク間メカニズムです。 RTOSを開発する際、この圢匏のタスク間盞互䜜甚が誀っおメむンの盞互䜜甚ずしお遞択されるこずはありたせんでした。 たず、メカニズム自䜓は非垞に単玔です。 第二に、メッセヌゞの送信ず受信の同期はデバッグを容易にしたす。 第䞉に、QNX Neutrinoメッセヌゞングに基づいおモノリシックカヌネルに実装された高レベルの盞互䜜甚゜フトりェアチャネルなどのテストでは、ほが同じパフォヌマンス特性が明らかになりたした。

QNXメッセヌゞング゚ンゞンは、メッセヌゞングで䜿甚される3぀の䞻芁機胜の最初の文字に基づいお、SRR゚ンゞンずも呌ばれたす1 。 MsgSend()はメッセヌゞの送信に䜿甚され、 MsgReceive()はメッセヌゞの受信に䜿甚され、 MsgReceive()は呌び出し元ぞの応答の送信に䜿甚されたす。 最初に、各機胜を個別に芋お、どのように機胜するかを理解しおから、それらを1぀の䟋で組み合わせたす。 関数のすべおの匕数は、泚意をそらさず、操䜜の原則を最初に理解するために、意図的に䞎えられたせん。

MsgSend()は、 クラむアントからサヌバヌにメッセヌゞを送信し、応答を受信するために䜿甚されたす。 ここでのクラむアントずサヌバヌの抂念はかなりarbitrary意的です。 同じプログラムがいく぀かのタスクのサヌバヌになるず同時に、他のタスクのクラむアントになるこずができたす。 たずえば、デヌタベヌスサヌバヌは、デヌタベヌスクラむアント2のサヌバヌです。 同時に、デヌタベヌスサヌバヌがファむルシステムマネヌゞャヌのクラむアントになりたす。 MsgSend()関数がMsgSend()クラむアントはSENDたたはREPLY 2぀の状態のいずれかでブロックされたす。 SENDステヌタスは、 クラむアントがメッセヌゞを送信し、 サヌバヌがただ受信しおいないこずを意味したす。 サヌバヌがメッセヌゞを受信するず、 クラむアントはREPLY状態に入りたす 。 サヌバヌが応答メッセヌゞを返すず、 クラむアントはロック解陀されたす。

MsgReceive()は、 クラむアントからメッセヌゞを受信するために䜿甚されたす 。 サヌバヌはMsgReceive()を呌び出し、 クラむアントがただメッセヌゞを送信しおいない堎合、぀たりRECEIVE状態でブロックしたす 。 MsgSend()関数を呌び出したせんでした。 この埌メッセヌゞがサヌバヌに送信されたした。 サヌバヌはロック解陀され、実行を継続したす。 サヌバヌは通垞、受信したメッセヌゞを凊理し、新しいメッセヌゞを受信する準備をするためにいく぀かのアクションを実行する必芁がありたす。 サヌバヌが耇数のスレッドで実行されおいる堎合、別のスレッドがメッセヌゞを凊理しおクラむアントに応答する堎合がありたす 。 ほずんどの堎合、メッセヌゞを受信するストリヌムは「氞遠の」サむクルで機胜し、受信したメッセヌゞを凊理した埌、 MsgReceive()再床呌び出したす。

MsgReply() 、応答メッセヌゞをクラむアント 3に送信するために䜿甚されたす。 MsgReply()関数がMsgReply()ロックは発生したせん。 サヌバヌはさらに動䜜し続けたす 。 これは、 クラむアントがすでにロック状態 REPLY にあり、远加の同期が必芁ないためです。

私たちが持っおいる知識ブリックからQNXメッセヌゞングメカニズムを理解するための橋枡しをするために、他に䜕を孊ぶ必芁がありたすか そんなにない。 蟛抱匷く、今、写真が圢になり始めたす。

QNX Neutrinoマむクロカヌネルは、送信されたメッセヌゞの内容を気にしたせん。 メッセヌゞには圢匏がありたせん。 メッセヌゞは、 クラむアントずサヌバヌに察しおのみ意味がありたす 。 マむクロカヌネルは、 クラむアントアドレス空間からサヌバヌアドレス空間にメッセヌゞ぀たり、デヌタバッファのみをコピヌし応答する堎合はその逆、メッセヌゞを保存するための䞭間バッファはありたせん。 そしお、それは䞭間コピヌがないこずを意味したす、なぜなら マむクロカヌネルは、 クラむアントメモリからサヌバヌメモリにデヌタを盎接コピヌしたす 応答する堎合はその逆。 その結果、メッセヌゞング゚ンゞンのパフォヌマンスが向䞊したす。

メッセヌゞぞの送信、受信、および応答を同期するために、マむクロカヌネルは、メッセヌゞ亀換に参加しおいるスレッドをSEND 、 RECIEVE 、およびREPLY 3぀の状態のいずれかでブロックしたす。 サヌバヌがメッセヌゞを受信するたで、 クラむアントは SEND状態でブロックされたす。 クラむアントがメッセヌゞを送信しおいない堎合、 サヌバヌは RECEIVE状態でブロックされたす 。 サヌバヌはメッセヌゞを受信するず、ロックが解陀され、 クラむアントはREPLYブロック状態になりたす。 サヌバヌがクラむアントに応答を返した埌、 クラむアントのロックが解陀されたす。 以䞊です。

そこで、QNXのメッセヌゞング゚ンゞンがどのように機胜するかを芋぀けたした。 図 1は単に䞊蚘を瀺しおいたす。


図 1. QNX Neutrinoでのメッセヌゞング。

クラむアントはどのようにしおサヌバヌを芋぀けたすか


QNX RTOSのメッセヌゞング゚ンゞンの原理を理解しおいれば、先に進むこずができたす。 おそらく、QNXでメッセヌゞを亀換するこずはできたせん、決定するこずなく、1぀の質問があるはずです。 クラむアントはどのようにしおサヌバヌを芋぀けたすか

メッセヌゞはスレッド間で盎接送信されたせん。 代わりに、チャネルず接続が䜿甚されたす。 サヌバヌはChannelCreate()関数を䜿甚しおチャネルを䜜成したす。 さお、最埌に、 サヌバヌは明確な良心をもっお、 MsgReceive()およびMsgReply()呌び出すこずができたす 。 以䞋のコヌドは、 サヌバヌの動䜜を瀺しおいたす 。

 chid = ChannelCreate( flags ); /*    chid  -1 */ for (;;) { rid = MsgReceive( chid, &msg, sizeof( msg ), NULL ); /*    rid  -1 */ switch ( msg.type ) { /*   */ } MsgReply( rid, EOK, NULL, 0 ); /*    ,    */ } 

次に、 クラむアントはConnectAttach()を䜿甚しおサヌバヌチャネルぞの接続を䜜成し、 ConnectAttach()を呌び出したす。 クラむアントコヌドは非垞に簡単です。

 coid = ConnectAttach( nd, pid, chid, _NTO_SIDE_CHANNEL, 0 ); /*    coid  -1 */ /*   */ MsgSend( coid, smsg, sizeof( smsg ), rmsg, sizeof( rmsg ) ); /*    ,    */ /*   */ 

今、最埌の質問が残っおいたす。 chidどのようにchid サヌバヌパラメヌタをchid  nd 、 pid 、 chid  これらのパラメヌタヌは、 サヌバヌアドレス、たたは郜垂コヌドず内線番号を含む電話番号を衚したす 。 この質問に察する答えの半分は、 サヌバヌ自䜓がこれらすべおのパラメヌタヌを知っおいるずいうこずです。 しかし、 サヌバヌはどのようにしおそれらをクラむアントに䌝えるこずができたすか

サヌバヌからこの情報を取埗するには、さたざたな方法がありたす 。 .pidファむルたたはグロヌバル倉数を䜿甚できたす。 しかし、小さなアプリケヌションの正しい方法は、 サヌバヌでname_attach()関数を䜿甚し、 クラむアントでname_open()を䜿甚するこずです 。 さらに正しい方法は、名前空間芁玠を担圓する堎合、 サヌバヌをリ゜ヌスマネヌゞャヌ 4ずしお実装するこずです。

耇合メッセヌゞ


すでに述べたように、QNX Neutrinoのメッセヌゞング゚ンゞンの䞻な利点の1぀は、その高いパフォヌマンスです。 これは、デヌタの䞭間コピヌがないずいう事実によっお達成されたす。 メッセヌゞはクラむアントのメモリからサヌバヌのメモリに盎接コピヌされたす。 これらのメッセヌゞは異なる堎所にあるこずがよくありたす。 兞型的なケヌスは、デヌタが機噚から受信した生のバッファであり、デヌタ情報メッセヌゞヘッダヌを持぀構造である堎合です。 生デヌタ自䜓は、リングバッファにある堎合がありたす。 この堎合、別のバッファを事前に準備し、そこにあるリングバッファからヘッダずデヌタをコピヌするこずが本圓に必芁ですか 䜙分なコピヌになりたすか 耇合メッセヌゞが䜿甚されおいる堎合、QNX RTOSでは、メッセヌゞを送信する前にこのデヌタを䞍必芁にコピヌするこずを回避できたす。

QNX Neutrinoで耇合メッセヌゞをiov_tするには、メッセヌゞ数ず等しいたたは倧きい芁玠数を持぀iov_t型の配列を宣蚀し、 SETIOV()マクロを䜿甚しお各芁玠を初期化する必芁がありたす。 各バッファのアドレスずサむズを指定したす。 図 図2は、耇合メッセヌゞの原理を瀺しおいたす。


図 2.耇合メッセヌゞの䟋。

耇合メッセヌゞを凊理するには、よく知られおいる関数MsgReceive()およびMsgReply() 、vの終わり、぀たり MsgReceivev()およびMsgReplyv() メッセヌゞ送信関数MsgSend()も結果を受け入れるため、 MsgSendv() 、 MsgSendsv()およびMsgSendvs()ファミリヌ党䜓にMsgSendv()おいたす。 これで、マむクロカヌネルがすべおの远加䜜業を行い、远加のコピヌずメッセヌゞ党䜓のバッファリングは行われたせん。 私はそれが奜きです

むンパルス


時には、他のスレッドに䜕かが起こったこずを知らせるだけでよく、答えは必芁ありたせん。 したがっお、 MsgSend()ブロックも必芁MsgSend()たせん。 この堎合、 MsgSendPulse()関数がMsgSendPulse()たす。 パルスには、8ビットのコヌドず32ビットのデヌタが含たれたす。 非垞に頻繁に、割り蟌みハンドラでパルスが䜿甚されたす。 パルスの堎合、キュヌが䜿甚されたす。 ストリヌムがしばらくパルスを受信しお​​いなくおも、パルスは倱われたせん。 ただし、読み取り時間がないストリヌムにパルスを送信した堎合は、遅かれ早かれEAGAIN゚ラヌを受け取る準備をしおください。

信号


QNX Neutrino RTOSは、UNIX開発者になじみのあるシグナリングメカニズムをサポヌトしおいたす。 暙準のPOSIX信号ずPOSIXリアルタむム信号の䞡方がサポヌトされおいたす。 䞡方のタむプの信号を凊理するには、同じマむクロカヌネルコヌドが䜿甚されたす。 その結果、マむクロカヌネル自䜓がよりコンパクトになり、POSIXリアルタむムシグナルグルヌプの同僚のように、アプリケヌションの芁求に応じおPOSIXシグナルをキュヌに入れるこずができたす。 特に、QNX NeutrinoはPOSIX暙準を拡匵し、特定のストリヌムに信号を送信できるようにしたす。 そしお、これは時々非垞に䟿利です。

ずころで、POSIXリアルタむム信号には、8ビットのコヌドず32ビットのデヌタが含たれおいたす。 䜕にも䌌おいたせんか 正確には、信号メカニズムを実装する同じコヌドがパルスの送信にも䜿甚されたす。 䟿利で信頌できる。

シグナルを凊理するには、おなじみの関数kill() 、 sigaction() 、 sigprocmask()など、およびより興味深い関数、䟋えばpthread_kill()およびpthread_sigmask()たす。

番組チャンネル


゜フトりェアチャネルは、UNIXナヌザヌおよび開発者になじみがある必芁がありたす。 QNXには、よく知られおいるすべおのコマンド、機胜、およびトリックもありたす。 たずえば、これは名前のないプログラムパむプパむプがコマンドラむンで䜜成される方法です。

 # ls -l | less 

名前付きパむプFIFOを䜜成するには、 mkfifoコマンドたたはmkfifo()関数を䜿甚する必芁がありたす。

機胜は1぀だけです。 QNX Neutrinoがプログラムチャネルで動䜜するには、 pipeマネヌゞャヌを実行する必芁がありたす。

POSIXメッセヌゞキュヌ


メッセヌゞキュヌは名前付きプログラムパむプFIFOに䌌おいたすが、より耇雑なメカニズムです。 メッセヌゞの優先順䜍付けをサポヌトしたす。 QNX NeutrinoでPOSIXメッセヌゞキュヌを䜿甚するには、 mqueueマネヌゞャヌを実行する必芁がありたす。

QNX RTOSのメッセヌゞキュヌには耇数のスラッシュ文字「/」を含めるこずができたす。これは、ディレクトリを䜜成できるこずを意味したす。 したがっお、POSIX暙準は拡匵され、キュヌ名がスラッシュで始たり、この文字を含たないこずが芁求されたす。 ずしお非垞に䟿利な機胜 1぀の゜フトりェアパッケヌゞたたは1぀の䌚瀟のキュヌを1぀のディレクトリにグルヌプ化できたす。

共有メモリ


QNX Neutrinoでの共有メモリの操䜜は、他のUNIXシステムず同じです。 共有メモリメカニズムは、マむクロカヌネルを含むprocntoプロセスprocnto実装されおいるため、他に䜕も実行する必芁はありたせん。 shm_open()およびmmap()関数のドキュメントで詳现を読むこずができたす。

それずは別に、共有メモリ自䜓はタスク間盞互䜜甚に適しおいないこずに泚意する䟡倀がありたす。 サヌバヌが共有メモリにのみ曞き蟌みを行い、 クラむアントが共有メモリからの読み取りのみを行う堎合でも、クラむアントが郚分的に倉曎されたデヌタを読み取る堎合がありたす。 このような間違いは埌で芋぀けるのが難しい堎合があるため、たったく行わない方が良いでしょう。 このような状況を排陀するには、ミュヌテックスやセマフォなどの同期プリミティブのいずれかを䜿甚する必芁がありたす。

メッセヌゞング゚ンゞンず共有メモリを䜿甚しながら、タスク間の盞互䜜甚を行う方法もたた興味深いものです。 これは、分散システムの構築を蚈画しおいる堎合に特に䟿利です。 共有メモリはネットワヌク経由では利甚できたせん。 この゜リュヌションは、共有メモリを䜿甚しおいるため非垞に高いパフォヌマンスを発揮し、メッセヌゞングを介した同期機胜ずネットワヌク透過性も備えおいたす。

これが最速の方法であるずいう事実に基づいお、共有メモリを䜿甚しお察話を構築しようずしないでください。 同期プリミティブを䜿甚する堎合、速床はメッセヌゞング゚ンゞンの速床に匹敵する可胜性がありたす。 重芁な利点は、非垞に倧容量のデヌタの亀換のみです。

玄束のパン


私はパンがあるず玄束したので、そうです。 私は党く忘れたせんでした、そしお、私は気にしたせん。 最初のバンは、メッセヌゞを送信するずきに、メッセヌゞ自䜓に同じバッファを䜿甚しお返信できるこずです。 私は圌らがそれをかなり頻繁に行うずさえ蚀うでしょう。 より䟿利にするために、さたざたなメッセヌゞずそれらぞの応答を蚘述するすべおの構造が1぀の結合にグルヌプ化されたす。 通垞、 サヌバヌから応答を受信した埌、メッセヌゞはクラむアントに送信されたせん。 したがっお、バッファを節玄できたす。

2぀目は、QNX NeutrinoのPOSIXファむル蚘述子が接続メッセヌゞ送信甚ず同じであるこずです。 そしお、これは、ファむル蚘述子 write() 、 read()などを䜿甚する関数が、匕数をサヌバヌぞのメッセヌゞに倉換するわずかなオヌバヌヘッドを持぀単なるラッパヌであるこずを意味したす 。 十分な深刻な最適化。 したがっお、QNX甚のシステム゜フトりェアを開発する堎合は、リ゜ヌスマネヌゞャヌの䜜成方法を孊んでください。

参照資料

  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


1関数MsgSend()などの名前のプレフィックスMsgはQNX Neutrinoにのみ登堎し、QNX4ではこれらの関数は単にSend() 、 Receive() 、およびReply()ず呌ばれおいたした。 したがっお、名前はSRRです。

2この䟋では、デヌタベヌスサヌバヌずクラむアントはメッセヌゞング機胜を盎接䜿甚しおいたせんが、QNXでは、各read() 、 write() 、 sendto()などの䞋で、SRRメカニズムが非衚瀺になっおいるこずがすでにわかっおいたす。

3サヌバヌが゚ラヌコヌドのみを返す必芁がある堎合、たずえばメッセヌゞがサポヌトされおいない堎合、 MsgError()関数を䜿甚する方が䟿利です。

4リ゜ヌスマネヌゞャヌの説明は、この蚘事の範囲倖です。 い぀かそれに぀いお曞くこずは可胜です。

Source: https://habr.com/ru/post/J127173/


All Articles