180 likes | 362 Views
オペレーティングシステム J/K. 2004 年 11 月 18 日 酒居敬一 ( sakai.keiichi@kochi-tech.ac.jp ) http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/OS2004/. Linux における API: システムコール. もっとも原始的なもの ソフトウェア割り込み 0x80 番 (int 80h) 引数はレジスタに設定する 戻り値はレジスタに設定される 一般的なもの C 言語の関数インターフェース API として使いやすい、プログラムを読みやすい
E N D
オペレーティングシステムJ/K 2004年11月18日 酒居敬一(sakai.keiichi@kochi-tech.ac.jp) http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/OS2004/
LinuxにおけるAPI: システムコール • もっとも原始的なもの • ソフトウェア割り込み0x80番(int 80h) • 引数はレジスタに設定する • 戻り値はレジスタに設定される • 一般的なもの • C言語の関数インターフェース • APIとして使いやすい、プログラムを読みやすい • libcでint 80hインターフェースに変換 • libcはUNIXにおける標準ライブラリの通称
LinuxにおけるAPI: ライブラリ関数 • システムコールをより使いやすくしたもの • C言語の関数 • システムコールと見かけ上は同じ • 標準的なものはlibcに含まれている • 標準ライブラリという形で、互換性をもたせたもの • プログラムの移植性があがる
segment .bss align=16 class=DATA use32 buf: resb 256 segment .text align=16 class=CODE use32 global _start ; default entry point align 16 _start: mov eax,3 ; read mov ebx,0 ; stdin mov ecx,buf ; address of buffer mov edx,256 ; size of buffer int 0x80 ; system call test eax,eax ; check return status js exit mov edx,eax mov eax,4 ; write mov ebx,1 ; stdout mov ecx,buf ; address of buffer int 0x80 ; system call test eax,eax ; check return status js exit jmp short _start exit: mov eax,1 ; exit mov ebx,0 ; return status int 0x80 ; system call end プログラム例(アセンブラ) • バッファを静的に確保 • 標準入力から読む • 標準出力へ書く • 終了 [sakai@star training]$ vi echo.asm [sakai@star training]$ nasm -f elf echo.asm [sakai@star training]$ ld echo.o -o echo [sakai@star training]$ size echo text data bss dec hex filename 63 0 256 319 13f echo [sakai@star training]$ ./echo askdjhaslkdjh askdjhaslkdjh [sakai@star training]$
[sakai@star training]$ objdump -d echo echo: ファイル形式 elf32-i386 セクション .text の逆アセンブル: 08048080 <_start>: 8048080: b8 03 00 00 00 mov $0x3,%eax 8048085: bb 00 00 00 00 mov $0x0,%ebx 804808a: b9 c0 90 04 08 mov $0x80490c0,%ecx 804808f: ba 00 01 00 00 mov $0x100,%edx 8048094: cd 80 int $0x80 8048096: 85 c0 test %eax,%eax 8048098: 78 19 js 80480b3 <exit> 804809a: 89 c2 mov %eax,%edx 804809c: b8 04 00 00 00 mov $0x4,%eax 80480a1: bb 01 00 00 00 mov $0x1,%ebx 80480a6: b9 c0 90 04 08 mov $0x80490c0,%ecx 80480ab: cd 80 int $0x80 80480ad: 85 c0 test %eax,%eax 80480af: 78 02 js 80480b3 <exit> 80480b1: eb cd jmp 8048080 <_start> 080480b3 <exit>: 80480b3: b8 01 00 00 00 mov $0x1,%eax 80480b8: bb 00 00 00 00 mov $0x0,%ebx 80480bd: cd 80 int $0x80 [sakai@star training]$ CPUは機械語しかわからない…
プログラム例(C言語) • 記述が単純。 • わかりやすい。 • よみやすい。 #include <unistd.h> int main(void) { char buf[256]; int cnt; while((cnt = read(0, buf, sizeof buf)) > 0){ write(1, buf, cnt); } return 0; }
システムプログラムの必要性 • 例: 入出力しながら一定時間ごとに時刻表示 • read()/write()するとプロセスは待ち状態になる。 • 時刻表示をするには? • 非同期 read()/write() をする。→ ポーリング • 時刻表示にシグナルを使う。→ 割り込み • スレッドを複数使用する。→ マルチスレッド処理 • 1と2にはただし、そのものずばりのライブラリ関数はない。 • システムコールを使う。 • 3にはライブラリがある。 • 2か3の方法を使うことが多い。使い分ける。
void timer_handler(int n) { char buf[256]; int cnt; snprintf(buf, sizeof buf, " %d %n", time(NULL), &cnt); write(1, buf, cnt); } int main(void) { struct itimerval timer; struct sigaction sa; char buf[256]; int cnt; sa.sa_handler = timer_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_restorer = NULL; sigaction(SIGALRM, &sa, NULL); timer.it_value = timer.it_interval = (struct timeval){ 1, 0}; setitimer(ITIMER_REAL, & timer, NULL); while(1) { if((cnt = read(0, buf, sizeof buf)) > 0){ write(1, buf, cnt); } } } シグナルによる実装例 • 1秒ごとに時刻表示 • エコーバック処理 これらを同時処理
#include <unistd.h> #include <pthread.h> void *timer(void *arg) { char buf[256]; int cnt; while(1){ sleep(1); snprintf(buf, sizeof buf, " %d %n", time(NULL), &cnt); write(1, buf, cnt); } } int main(void) { char buf[256]; int cnt; pthread_t thr; pthread_create(&thr, NULL, timer, NULL); while((cnt = read(0, buf, sizeof buf)) > 0){ write(1, buf, cnt); } return 0; } マルチスレッドによる実装例 • 1秒ごとに時刻表示 • エコーバック処理 これらを同時処理
イベントドリブンシステム • 入力すべき文字がある • 出力が可能である • 一定時間が経過した • マウスを動かした… などなど… これらをイベント(事象)としてとらえ、 イベント発生を受けて動作するシステム
イベントドリブンシステム • 発生したイベントの通知方法 • (ポーリング) • シグナル送信・メッセージ送信 • スレッドのwake up • 処理を割り付ける方法 • (条件分岐) • シグナルハンドラ・コールバック関数 • マルチスレッド イベントと処理を効率的にバインド(bind)することがミソ
イベントドリブンシステムにおける有効性 UI(User Interface)のような非同期で不定間隔で処理が必要な場合 • 処理が必要な状況→イベント発生 • 処理はイベントとバインドする • OSの仕組みを利用すれば効率的 • イベントと処理の組み合わせが自在 • イベント発生とイベント処理を分離でき構造がすっきりする。 • シグナルやメッセージパッシングを使うとOO的
リアルタイムシステムの構築手法 • 処理オーバーヘッドの削減 • 応答時間が一定の範囲内にあることを保証 • 必要な処理時間の予測を行う • 複数の処理要求が発生しても時間内に完了 • 割り込み処理として記述する(モニタなし) • 割り込み処理はスケジューラを呼ぶことにし、ディスパッチャと分離する(モニタとして実装)
リアルタイムモニタとして実装するとき • 非プリエンプティブマルチタスク • 処理時間がわかっている • 処理が完了すべき時刻(デッドライン)の要求を満たす • メモリは領域の管理だけ • タスクは自由に相互に参照可能 • ユーザー空間での割り込み処理 • シグナル機構に変換しない
プロセッサへの割り込み→イベント発生 • タスクはそれにより順次起動される • 再帰的に起動されるタスク • そうでないタスク • タスクが待ち状態に入る→イベント発生 • 同期通信機構→タスクからのイベント発生 • スケジューラはイベントの発生ごとに呼ばれる • I/Oの待ちによるCPUの空き時間を利用して、 多重にプログラムを走行させる
例:モーター制御 • ステッピングモータを駆動することで、位置を制御 • 励磁信号はプロセッサが生成 • ハードリアルタイム処理 • モーター駆動速度には上限がある • モーターの加減速度には上限がある
フィードフォワード制御とフィードバック制御の併用フィードフォワード制御とフィードバック制御の併用 • 制御量は位置、位置のずれ(偏差)をもとに制御 • 偏差を最小にするようにフィードバック制御を使用 • 偏差が残ると誤差となるので、PID制御がよく使われる • P: Proportional • I: Integral • D: Differential • 位置制御の結果が静定する時間を短縮するため フィードフォワード制御も併用 • 制限事項とともに、制御の計算量が必要となる
カウンター割り込みを使用 • カウント値の更新により励磁間隔を変更 • カウント値の更新間隔は励磁間隔以下 • カウント値は位置制御部からの指示