• 検索結果がありません。

RTLinuxモジュールの動き

ドキュメント内 B5size manual.dot (ページ 50-53)

第 3 章  初歩の RTLinux プログラミング 27

3.7  LinuxプロセスからRTLinuxモジュールを制御するプログラム

3.7.3  RTLinuxモジュールの動き

ここでは、RTLinuxモジュール(module3.o)の動きに注目して見てみます。

まず、RTLinuxモジュール内の各リソースとRTLinuxスレッド,ハンドラの生成関係を下図に示しま

す。

RT-FIFO

スレッド&ハンドラのコード init_module

ハンドラ(my_handler)

RTLinuxスレッド(my_task) FIFO1(GET_HANDLER_FIFO)

FIFO2(GET_TASK_FIFO)

FIFO3(SET_TASK_FIFO)

cleanup_module

生成 破棄

Linuxプロセスからの指令を受け取るハンドラ(my_handler)と、RTLinuxスレッド(my_task)が生成/

破棄されています。

次に、RTLinuxモジュール内での相互関係を示します。

ハンドラ(my_handler)

RTLinuxスレッド(my_task) Linuxプロセス

周期実行 ID_START ID_STOP

開始 停止

counter変数  ←インクリメント

  FIFO1(GET_HANDLER_FIFO)

FIFO3(SET_TASK_FIFO)

FIFO2(GET_TASK_FIFO)

RTLinuxモジュール内で中心となるのは、周期実行を行うRTLinuxスレッド(my_task)です。この RTLinuxスレッドは、Linuxプロセスからの指令により、周期実行のスタート(ID_START),ストッ プ(ID_STOP)を行います。スタート後の周期実行中、RTLinuxスレッドは内部のcounter変数を周期 ごとにインクリメントします。(将来、カスタマイズするならば、例えば、ここにDIOやAD/DA等 の周期的な制御を入れると良いでしょう)

LinuxプロセスからRTLinuxスレッドへの指示は、ハンドラ(my_handler)を経由して行われます。こ のハンドラは、Linuxプロセスからの指示を、RTLinuxスレッドに、そのまま送っています。(将来、

RTLinuxスレッドを2つ以上に増やした時、このハンドラで、操作するスレッドを集中的に管理す ると良いでしょう)

ハンドラとRTLinuxスレッドは、RT-FIFOによって、情報の交換を行います。

RT-FIFOの生成と削除は、init_module関数とcleanup_module関数で行っています。

以降では、処理順にこれらの処理を解説します。

(89〜99行目:rtf_destroy、rtf_create関数)

RT-FIFOを生成するのは、rtf_create関数です。破棄はrtf_destroy関数です。

コードでは、rtf_destroy関数を呼び出した後、rtf_create関数を呼び出しています。

通常であれば、init_module関数を実行する時、RT-FIFOは生成済みということは考えにくいのです が、ここでは保険として、rtf_destroy関数で明示的に削除を行っています。

RT-FIFOのサイズは、各RT-FIFOごとに変えています。

特にRTLinuxスレッドからLinuxプロセスへ結果を返却するRT-FIFO(99行目の、SET_TASK_FIFO)

では、”sizeof(long:4バイト) * BUFF_SIZE(100個) = 400バイト”のバッファサイズを確保しています。

これは、RTLinuxスレッドに格納した情報を、即座にLinuxプロセス側で取り出せることは考えに くいため、ある程度RT-FIFOに情報が溜まっても、処理が続けられるよう(バッファをオーバーフ ローしないよう)に、大きめのバッファを確保しています。

実際のリアルタイムプログラミングでも、2つのプロセス間が非同期に動作する場合、バッファサ イズに、余裕を持たせることは重要です。

(91行目:rtf_create_handler関数)

rtf_create_handler関数は、ハンドラ(my_handler)を生成する関数です。

このハンドラでは、指定されたRT-FIFOにメッセージが溜まると呼び出される、明示的なイベン

(69〜73行目:my_handler関数のwhileループ)

ハンドラ(my_handler)関数では、このwhileループがメインとなります。

ここでは、Linuxプロセスと繋がるRT-FIFOから送られるデータを受け取るために、rtf_get関数で 待機します。

受け取ったデータは、ここでは、rtf_put関数にて、そのままRTLinuxスレッド(my_task)と繋がる RT-FIFOに送っています。

簡単なイメージを、下図に示します。

RT-FIFO RT-FIFO

my_handler

ハンドラ

rtf_get rtf_put

Linuxプロセス側 RTLinuxスレッド側

将来、RTLinuxスレッドを2つ3つと増やした場合、ここをLinuxプロセスから各RTLinuxスレッド へメッセージを分配するための、集配所として追加すれば良いでしょう。

RT-FIFO RT-FIFO

my_handler

ハンドラ

rtf_get rtf_put

Linuxプロセス側 RTLinuxスレッド側

RT-FIFO

RT-FIFO

(24〜56行目:my_task関数のwhileループ)

RTLinuxスレッド(my_task)では、このwhileループがメインとなります。

ここでは、ハンドラと繋がるRT-FIFOから送られるデータをrtf_get関数で受け取り、その指示に従 い、周期実行のスタートおよびストップを行います。

周期実行を動作させている時、内部のcounter変数がインクリメントされていきます。

このインクリメントされた値は、rtf_put関数を用いて、Linuxプロセスに繋がるRT-FIFOに送られ ます。

29行目のrtf_get関数は、周期実行が行われている/行われていないに関わらず、ここでRT-FIFOか らのデータ待ちになってしまうと思われるかも知れません。

しかし、実際には、rtf_get関数の呼び出しは、RT-FIFOからのデータがあれば、29〜47行の処理を 行い、無ければ50行以降の処理を続けます。

33〜46行のswitch文では、Linuxプロセスから送られてきた指示に対する処理が記述されています。

動きを以下に示します。

ID_START value変数の値をms単位の実行周期として、pthread_make_periodic_np関数を呼び出し、

自身の実行周期の間隔を指定する。

ID_STOP pthread_suspend_np関数を呼び出し、自スレッドをスリープ状態にする。

50〜55行の処理は、周期実行している時の、処理コードです。

内容は、内部counter変数をインクリメントし、counter変数の値を、rtf_put関数を使って、RT-FIFO に書き込み続けています。

ここでやっているのは、非常に単純な処理ですが、この処理をDIOやAD/DA等に置き換えて見る と、様々なやり方が想定できることでしょう。

例えば、周期実行の部分に、1件のAD入力関数を配置するだけで、サンプリング間隔を簡単に可 変することが実現できます。

■関数解説

★rtf_create

RT-FIFOを生成します。

1引数でRT-FIFOID値を、第2引数でサイズを指定します。

生成したRT-FIFOを破棄するには、rtf_destroy関数を用います。

★rtf_create_handler

この関数は、ユーザ空間からRT-FIFOにデータが書き込まれた際に、呼び出される関数を登録します。

1引数には、RT-FIFO作成時に指定したID値を指定します。

2引数には、RT-FIFOにデータが書き込まれた際に、呼び出される関数を指定します。

この関数は、ユーザ空間からRT-FIFOにデータが書き込まれた際に呼ばれる関数を登録しますが、カー ネル空間からアクセスされた(rtf_put、rtf_get関数を使用した)場合に呼ばれる関数を登録するには、

rtf_create_rt_handler関数を使用します。

★pthread_wakeup_np

この関数を呼ぶことで、指定したRTLinuxスレッドの実行を再開することができます。

★pthread_suspend_np

引数により指定したRTLinuxスレッドをpthread_wakeup_npが呼び出されるまで中断します。

ドキュメント内 B5size manual.dot (ページ 50-53)