Download追加 2005/07/16 システムコールの簡易リアルタイム化追加 2006/07/24 kernel-2.6.15への移行追加 2006/10/22 Debian Flash Memory版追加 2006/10/31 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
目 次 1 はじめに 2 概 要 3 プログラミング条件 4 機能説明 5 動作及びソース 6 結 果 7 ドライバ内からのシステムコール 8 Download |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1 はじめに | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
実際に現場にいると、単に早いレスポンスを要求するためLinux等の汎用システムが使えない場合が多い。言い換えれば、間に合えば良いシステムは数多くあるようだ。このようなシステムでLinuxを使う一方法を述べる。 このような場合、デバイスドライバで処理するのが一般的と思われる。このデバイスドライバ内で簡単なシーケンスプログラムを組むのは容易ではない。ところがRT−Linux等は、この常識を破ってくれたので、次のようなシステムを作成してみた。 ○ 音声処理等の早いレスポンスを要求する処理をターゲットとする。 ○ タスクの実現にはKernelThreadを使用する。 ○ 従って、タスクスイッチはLinuxのKernelThreadコントロールに依存する。 ○ その意味でSemiRealtimeである。 ○ マルチタスクの最低限の機能としてセマフォとメッセージキューをサポートする。 ○ 1msecからLinuxSystemTimeまでの時間分解能を目標とする。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 概 要 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
さし当たって作成した関数であり、論理的には抜けている機能が数多くあるが、実用上差し支えない程度に絞ってある。(手抜きとも言う。
例えばIntBindに対するUnbindとか。 一旦開始してしまえばシステム終了するまで動作すると仮定している。) 主な機能は次の通りである。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3 プログラミング条件 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
プログラミングはデバイスドライバ作法に依る。 タスク(thread)のスケジュールはKernelがサービスする。従って、RealTime性能は期待できないが、割り込みとの併用で素早い動作が期待できる。 なお、kernel2.6への移行により、kernel-preemptionが1msecのシステムクロックと相まって、あるレベルのRealTime性を持たせることができる。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4 機能説明 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・1 割り込みの設定及び割り込みハンドラの設定 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itIntBind (int vector, void(*routine)(void*), void *param)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・2 割り込み設定の解除 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itIntUnbind (int vector)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・3 割り込み禁止 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itIntLock ( )
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
システムを割り込み禁止とする。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・4 割り込み禁止解除 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void itIntUnlock (int flags)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
flags : itIntLockの戻り値 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・5 デバイスドライバ内でのThreadの作成 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itThreadCreate (int *tid, struct it_thread_attr
*attr,
void *entrypoint, void *arg)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ThreadのPriorityの設定 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itThreadPriority (int *tid,
unsigned long priority)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Threadの 実行 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itThreadStart (int *tid)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・6 当該threadのスリープ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void itTaskDelay (int msec)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
msec : threadのスリープ時間(msec単位) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・7 セマフォの作成 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itSemInit (int val, struct semaphore *sid)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・8 セマフォを取得する | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
セマフォが「empty」の(取得できなかった)場合はタスクは待ち状態にされる。「full」の(取得できた)場合及びタイムアウトでコントロールが戻る。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itSemTake (struct semaphore *sid, int timeout)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・9 セマフォを与える | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
既にこのセマフォに対して待ち状態あるタスクを実行状態にする。 もし 待ちタスクが無い場合は、このセマフォを「full」状態とする。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Int itSemGive (struct semaphore *sid)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・10 メッセージキューの作成 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
メッセージキューを作成しmsghを返す。キューの数及びメッセージの長さは固定です。 メッセージの長さはこの値を超えないこと。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
struct msgQhandle *itMessageCreate ( )
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
内容要約 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・11 メッセージ送信 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
メッセージキューにメッセージを送り込む。 待ち状態にあるタスクは実行状態に戻されます。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itMessageSend (struct msgQhandle *msgh,
void *message, int len)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
内容要約 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4・12 メッセージ受信 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
メッセージキューからメッセージを取得する。キューが空の場合待ち状態に移行する。 待ち状態の場合、新にメッセージがキューに入るとコントロールが戻り実行状態になります。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int itMessageReceive (struct msgQhandle *msgh,
void *message, int len, int timeout)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
内容要約 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
5 動作及びソース | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ちょっとテストプログラム | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
どうせならとkernel-2.6.15-1.2054_FC5へ移行した。kernel-2.6ではHZ=1000とkernel-preemptionがサポートされ、それだけでリアルタイムが実現できそうな勢いですが、実際はそうはいかないようです。 ここではkernel-2.6.15-1.2054_FC5のHZを1000に変更するのみのkernel-2.6.15-prepを作成し使用した。 使用マシンはPentium4-1.5Mhz、ASUS P-4B。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
5・1 タイマーループの精度 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
標準のPC互換機では空いたタイマー割り込みが無いので、システムタイマーとしてシステムクロック(HZ)を使用することになる。従って、タイマー精度というよりは、Voluntary Kernel Preemptionが単位システムタイム(HZ)で制御を得られるかのテストになる。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
他のタスクを同時に動作させた場合でも±100usec以内に収まるようです。
当然ながら遅延時間の分解能はHZにより決まり、この場合1msecです。ということは、他のCPUで割り込みで行っている遅延ループと異なり、1msecは正確でありHZをとり逃さない限り
時間誤差が累積することは無い。 ここでは、この1mesecに対してどのくらいふらつくかが焦点になる。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
5.2 サウンド入出力 システムコール ( kernel-preemptionとは共存不可) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
サウンドは/dev/dspおよび/dev/audioのfragmentが被テスト機では最小で1024bytesまでである。 これは8khz、16bitMonauralで64msec分であり、リアルタイムテストには不向きであるが10msec分のデータ毎の処理をしてみた。 まあカーネル内でこんなこともできますよという例にしかなりませんが。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
これは意味が無いので時間を計測していないが、音声は途切れることなく動作する。 というのは、Audio入力は1024バイト溜まらないとデータが出てこないし、Audio出力は1024バイト溜まらないとスピーカに出力しない。 即ちバッファ1024バイトある格好になるので、スムースに動作するのは当たり前ですが・・・。 一方サウンドドライバに潜り込んでいる時間が長くなり、そのため他のタスクの起動時間のゆれは100usec程度なることもある。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
なお、VIA Ezra 665Mhz上でのUSBヘッドセット(/dev/dsp1)ではfragmentは最低16バイトであった、8khz、16bitMonauralでは 1msecに相当する。 Via665Mhzでのテストではaudioによる他のタスクwakeupのふらつきは10usec以下になっている。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
5.3 UDPシステムコールのテスト (kernel-preemptionとは共存不可) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
以前から制御データを遅滞無く送信するのに苦労していた。これをデバイスドライバ内から直接送信できれば安定した送信が期待できる。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
結果は5.1と同様に1msec±100usec内の精度で送信が実行されている。おそらく外部割込みで動作しているようなタスクで、外部イベントに同期して通信するものには100usec以内の時間精度で送信できる可能性がある。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
6 結 果 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
実際動作させた場合、(pentium4-1500Mhz)CPUの負荷状況等によりますが、1msec以上の周期でタスクの起動は問題なく動作する。
特にマルチタスク的な動作を要求するアプリケーションではプログラムがすっきり出来上がるので重宝に使っています。 ただし、デバイスドライバと同様の注意は必要です。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
7 ドライバ内からのシステムコール (kernel-preemptionとは共存不可) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
より早いレスポンスを得るためにはカーネル内からシステムコールを呼べれば、より優先度が高くオーバヘッドも少なくレスポンスは良いはずです。 そこでシステムコールのうちopen、read、write、ioctl、closeをカーネル内から呼べるサービを追加した。 しかし、kernel-2.6のkernel-preemptionとは共存できません。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int it_open(const char *pathname, int flags, mode_t mode);
ssize_t it_read(int fd, const void *buf,size_t count);
ssize_t it_write(int fd, const void *buf,size_t count);
int it_ioctl(int fd, unsigned long request, char *argp);
int it_close(int fd);
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
また懸案であったカーネルからのソケットの呼び出しも、socket、 setsockopt、 getsockopt、bind、 sendto、recvfromのサービスを追加した、UDP通信に威力を発揮する。ソケットは他にも使われることも多くサウンド等と異なり専用になり難 いため、音声/映像等のRTP(UDP)通信を除いて濫用は避けるべきであろう。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8 DOWNLOAD (FedoraCore5) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
使用法 デバイスドライバ mudrvtest.tgz と testapp.tgz をダウンロードして各々適当なディレクトリに解凍する。 makeすればドライバモジュールとテストアプリが出来上がります。 とはいえ、kernel-2.6になってから、使用するkernel-2.6.xxxをコンパイルした環境でドライバモジュールを作成しなければならなくなったようです。 従って、予めkernel-2.6.15-1.2054_FC5のソースを取得する。
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8・1 Via Ezra のフラッシュメモリ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
まず、基になるDebian3.1-kernel-2.6.8-3-1386の最小システムを
ここ から持ってくる。 内容はDebianのインストールを可能とする最小のシステムのみが入っています。(注意)正味256Mbあります。 CFはbuffalo RCF-X 256MBを対象にして、IDE(1,1)2番目のチャンネルのマスターにアサインしています。 ダウンロードしたファイルはCFのイメージそのものですから、書き込み可能なLinuxマシンにてddコマンドでCFに書き込んでください。(これはターゲットでは/dev/hdcになります。) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
なお、"root"のpasswdおよびuser"admin"のpasswdは共に"admin01"です。 audioは組み込みのものを使わないでUSBヘッドセット(/dev/dsp1)を使用します。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
実行は
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||