次のページ 前のページ 目次へ

6. プロセス間通信

これまで見てきた例プログラムは、リアルタイムプロセスと呼ばれるものです。 アプリケーションプログラムのすべての部分をリアルタイム用に書く必要は ありません。プログラムの中でも正確な時間制限を要求される部分だけが リアルタイムプロセスとして書かれるべきであることが分かります。 それ以外はユーザ空間で実行するように書いてかまいません。 ユーザ空間のプロセスは、多くの場合リアルタイムスレッドよりも作成、実行、 そしてデバッグが容易です。しかしその一方で、ユーザ空間にある Linux プロセスとリアルタイムスレッドの間で通信を行う手段を用意すべきです。

プロセス間通信を行う手段はいくつかあります。通信を行う最も有力で 一般的な手段であるリアルタイム FIFO について議論します。

6.1 リアルタイム FIFO

リアルタイム FIFO は、一方向のキューです(First In First Out:先入れ先出し)。 つまり一方からプロセスが FIFO にデータを書くと、FIFO のもう一方から情報が別のプロセスに読みこまれます。通常、 そうしたプロセスの片側がリアルタイムスレッドで、 もう一方がユーザ空間のプロセスになります。

リアルタイム FIFO は、実際にはメジャーナンバー150のキャラクターデバイス (/dev/rtf*)です。リアルタイムスレッドは、各 FIFO を参照するのに整数を用います(例えば /dev/rtf2 なら2)。 FIFO の数には制限があります。FIFO を扱う関数には、rtf_create(), rtf_destroy(), rtf_get(), rtf_put() などがあります。

一方、Linux のユーザプロセスはリアルタイム FIFO を普通のキャラクターデバイス とみなします。そのため、open(), close(), read() そして write() といった関数がこれらのデバイスに対して利用できます。

6.2 FIFO を利用するアプリケーション

まず PC のスピーカーから(二つの音だけからなる)音楽を演奏する簡単な C プログラム(ファイル名は pcaudio.c)を考えてみましょう。当面は、 音符を鳴らすにはキャラクターデバイス /dev/rtf3 に書きこむだけで よいことにしましょう(後で、この FIFO (/dev/rtf3)から読みこみ、 PC のスピーカーに送信するリアルタイム時間プロセスを考えます)。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define DELAY 30000

void make_tone1(int fd)
{
        static char buf = 0;
        write (fd, &buf, 1);
}

void make_tone2(int fd)
{
        static char buf = 0xff;
        write (fd, &buf, 1);
}

main()
{
        int i, fd = open ("/dev/rtf3", O_WRONLY);
        while (1)
        {
                for (i=0;i<DELAY;i++);
                make_tone1(fd);
                for (i=0;i<DELAY;i++);
                make_tone2(fd);
        }
}

さて、上に示したプログラム(pcaudio.c)をコンパイルして走らせると、 方形波に相当する規則的な音を生成するはずです。 しかしその前に '/dev/rtf3' から読みこみを行い、対応するデータを PC のスピーカーに送信するモジュールが必要です。このリアルタイムプログラムは、 rtlinux のソースツリー (/usr/src/rtlinux/examples/sound/)で見つけられます。'insmod' コマンドを用いて sound.o モジュールを組みこんでください。

デバイスから読みこみを行うモジュールを組みこんだので、 プログラムを実行できるようになりました('gcc' でコンパイルし、 それによってできた 'a.out' を実行してください)。 システム内に他の(時間を消費する)プロセスがない場合は、 プロセスはある程度規則的な音を生成します。しかし、別のコンソールで X サーバが起動されていると、無音部が長くなります。また 'find' コマンドを(/usr ディレクトリにあるファイルに対して)実行したりすると、 音像はすっかりゆがんでしまいます。こうなるのは、我々が非リアルタイム的に FIFO 上にデータを書きこんでいるからです。

それでは、音が何の障害もなく生成されるように、リアルタイムにこのプロセス を走らせる方法を考えます。まず上記のプログラムをリアルタイムなプログラム に変換します(ファイル名は rtaudio.c)。

#include <rtl.h>
#include <pthread.h>
#include <rtl_fifo.h>
#include <time.h>

#define FIFO_NO 3
#define DELAY 30000
pthread_t thread;

void * sound_thread(int fd)
{
        int i;
        static char buf = 0;
        while (1)
        {
                for(i=0; i<DELAY; i++);
                buf = 0xff;
                rtf_put(FIFO_NO, &buf, 1);

                for(i=0;i<DELAY;i++);
                buf = 0x0;
                rtf_put(FIFO_NO, &buf, 1);
        }
        return 0;
}

int init_module(void)
{
        return pthread_create(&thread, NULL, sound_thread, NULL);
}

void cleanup_module(void)
{
        pthread_delete_np(thread);
}

まだ行ってないなければ、sound.o モジュールをカーネルの中に「プラグイン」 してください。(前に解説した通りに)それ用の Makefile を書き、 上に示したプログラムをコンパイルして 'rtaudio.o' モジュールを作成してください。 このモジュールを組みこむ前に、もう一つ行っておくことがあります。 上記のプログラムが無限ループの中を回ることに注意してください。 つまり、スレッドのスリープか停止を行うコードを入れないと、 そのスレッドは実行を止めません。簡単に言えば、PC のスピーカーは音を鳴らし続け、何か他のことを行うにはコンピュータを 再起動しなくてはならなくなります。

そこで、スレッド自身が音の間に遅延を入れるように、(sound_thread() 関数の)コードを少しだけ変えてみましょう。

void * sound_thread(int fd)
{
        static char buf = 0;
        pthread_make_periodic_np (pthread_self(), gethrtime(), 500000000);

        while (1)
        {
                pthread_wait_np();
                buf = (int)buf^0xff;
                rtf_put(FIFO_NO, &buf, 1);
        }
        return 0;

}

今度は、'rmmod' コマンドを用いてモジュールを削除するだけでプロセスを 停止させられます。

ここまでリアルタイム FIFO がプロセス間通信でどのように利用できるかを 見てきました。また RTLinux が本当に必要であることが、 上記の例からお分かりいただけたでしょう。


次のページ 前のページ 目次へ