Operating System Lecture 01/08

## 去年の宿題

## 割り当てられた教科書の問題の回答はメールで

Subject: Report Operating System Lecture 12/18

というSubject で提出してください。

## 前回の復習

## Unix の lockf

## Unix でのプロセス間通信と、Real-time 処理

## Unix の API (POSIX によって規定されている) による、プロセス間通信と Real-time 処理を調べよう。

### 問題 (Busy Wait )

### 以下のプログラムのUnix での問題点を指摘せよ。

for (;;) {
if ( c=kbhit() )
process(c);
}

(kbhit() は、MSDOS で良く使われる、キーボードが押されていたら、そのキーコードを返す関数。Unix のマニュアルには載っていません)

C-FAQ をWWW で探して、kbhit() が Unix では使われない理由を調べよ。

速さと言う点ではどうだろう?

## 実際に kbhit を作ってみる

NONBLOCKING モードを使ったread
fcntl で設定する

## signal による同期

あるイベントで、呼び出される関数を指定する。

signal では情報を渡すことはできない。

signal によって中断された system call の取り扱いはどうする? エラーとして良いのか?

## socket によるプロセス間通信

## 基本的には、

あっちのプロセスでwriteしたものが、
こちらのプロセスで読める

それだけ。問題は、

どうやって、相手を指定するのか?

である。

共通の親を持つならば、

socketpair, pipe

を使うことができる。

共通の親を持たない場合は、

Unix file system の名前空間を使う
ネットワークの IP address + Port number を使う

という手法がある。前者は、もちろん、ネットワーク経由には使えない。

socket は双方向なので、便利。(pipe は違う)

Perl による例題

## redirect と pipe

## 標準入出力の切替えには、close と dup を使う。

socket は、Unix に取っては file の一種であり、プロセス毎に番号(file descriptor) で管理されている。

0 標準入力 STDIN
1 標準出力 STDOUT
2 標準エラー出力 STDERR

close して open すれば、その番号が振られる。既に、open されているものをdup (duplicate ) しても良い。

以下は、3年生の shell の課題の一部である。

#include <stdio.h>
const int debug=1;
main() {
char command1[]="wc";
char command2[]="cat /etc/termcap";
int pfd[2];
int save_in;
int pid;
pipe(pfd);
if(pid = fork()){
save_in = dup(0);
dup2(pfd[0],0);
close(pfd[1]);
system(command1);
if(debug) fprintf(stderr,"waiting %d\n",pid);
dup2(save_in,0);
waitpid(pid,NULL,0);
if(debug) fprintf(stderr,"done %d\n",pid);
return;
}else{
if(debug) fprintf(stderr,"forked pid %d\n",getpid());
dup2(pfd[1],1);
close(pfd[0]);
system(command2);
exit(0);
}
}

## socket による通信の待ち合わせ

bind

socket に名前をつける

connect

TCP connection を張る

accept

TCP connection を受け取る

TCP connection を通して、socket channel そのものを渡すこともできる。=> (fork の例題)

## サービスモデル

server.pl
と client.pl
を動かしてみて、サーバの動きを理解しよう。

### 問題

### server.pl
を使って、簡単なアクセスカウンター (何回アクセスしたかを数える)を作ってみよ。

## サーバ・クライアントモデル

デーモン (daemon )

## サービスとトランザクション

## サービス内、トランザクション内の並列性

Lock をどのように実現しているかを考えよう。

## NFS

## RPC と UDP という connection less の通信を使って実装されている。

lock は、lockd という daemon を使う。

## WWW counter

## WWW server は fork するので、ファイルを lock することにより同期を取ることが多い。なので、非常に重い。

File を配達するだけの WWW server と、CGI を処理するserverを分離するのが効果的。Security 的にも望ましい。

## Micro Kernel

## OS のサービスのうち、

プロセスの作成、削除
スケジュール
メモリ管理
プロセス間通信

を除くと、その他のサービスは、すべて、サーバによって実現できる。このようにすることによって、OS の最小限必要な部分を抜きだしたものを

Micro Kernel

という。

Micro Kernel は、プロセス間通信が増えるので、効率は良くないとされている。しかし、OS の構造の見通しの良さ、拡張性などに利点がある。効率は、プロセス間通信の高速化などによりカバーできる。

Windows NT
Mach OS (Mac OS X)

などが実用的に使われている。Windows/Mac OS 9は違います。

## select による同期

## Unix では、select call が万能であり、ほとんどの同期は select
を使って実現できる。

しかし、ファイルと関係しないので、計算をセーブする場合には、ファイル処理を自分で行なう必要がある。

## 問題 (keyrecord/keyplay)

## real-time application を作ってみよう。「キーボードの入力を時間を含めて忠実に再現する プログラムを作れ」

ダメな例

NONBLOCKING モードを使ったread
fcntl で設定する

良い例

select を使った例を考える
サンプルコードを見てみよう
select を使わない例を考える
ioctl でreadが一文字で戻って来るようにする
man termios

時間をμsec 単位で測るには?

int gettimeofday(struct timeval *tp, struct timezone *tzp);

を使う。

時間は、usleep で稼ぐ。

void usleep(unsigned int microseconds);

間違っても100万回ループしたりしない。

keyrecord のサンプルコード
RCS って何?

mkdir RCS
ci -l
co -l
rcsdiff

kbhit() を Unix で作ってみよう。ダメな例を実装してみて、どれくらいダメか調べよう。

## Application の Perfomance Tuning

## Performance だけで良いのか? Real-time プログラムにとって Performance
とは何か?

このkeyrecord の時間の誤差はどこから来るの? Real-time OS とは?

出力ファイルを人間が読めない。出力ファイルを人間が読めるようにするには?

## 宿題(1) fork する daemon

## server.pl
を man perlipc などを参考に、fork するように書き換えて見よ。fork する方が適しているサービスにはどんなものがあるかを考えて実装してみよ。(C で書く場合は、課題で行なう stream.c の getstream を使うのが良い)

アクセスカウンタを fork する server で作る場合には、lock 等が必要になる。lock を使う場合はWWWの演習で出て来る。また、アクセスカウンタ用のサーバを作ることにより、実現することもできる。lock と専用サーバの利点と欠点、向いているサービスなどについて考察せよ。

## 宿題(2) 定期的な実行

## 決まった時間で実行するには、setitimer というのを使う。signal が来るので、sigpause で待とう。

void check(void)
{
/* this function does nothing. */
}
main() {
....
struct itimerval itv ;
int simt = 0, sent = 0, rect = 0 ;
itv.it_interval.tv_sec = 0 ;
itv.it_interval.tv_usec = TIMEDELTA * 1000 ;
itv.it_value.tv_sec = 0 ;
itv.it_value.tv_usec = TIMEDELTA * 1000 ;
signal(SIGALRM, (void (*)(int))check) ;
setitimer(ITIMER_REAL, &itv, NULL) ;
for (;;) {
sigpause(sigblock(0L)) ;
do someting....
}
}

または、select のtimeout を使っても良い。(こちらの方が簡単か?)

どちらかの方法を使い、keyrecord に、途中で時間を表示するコードを足してみよう。

## 課題

## 課題 7. WWW プログラミング </a>をさ来週までに行うこと。レポートはメールで

Subject: Report Operating System Lecture 01/12

というように、課題を出した日付をサブジェクトに入れたメールで提出して下さい。

Operating System Lecture 01/08

去年の宿題
前回の復習
Unix でのプロセス間通信と、Real-time 処理
問題 (Busy Wait )
実際に kbhit を作ってみる
signal による同期
socket によるプロセス間通信
* Perl による例題
redirect と pipe
socket による通信の待ち合わせ
サービスモデル
* server.pl
* client.pl
問題
* server.pl
サーバ・クライアントモデル
サービスとトランザクション
NFS
WWW counter
Micro Kernel
select による同期
問題 (keyrecord/keyplay)
* keyrecord のサンプルコード
Application の Perfomance Tuning
宿題(1) fork する daemon
* server.pl
宿題(2) 定期的な実行
課題

Shinji KONO / Tue Jan 8 06:18:00 2002