情報学類 分散システム 2008年12月02日 筑波大学システム情報工学研究科 コンピュータサイエンス専攻, 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2008/2008-12-02
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/
図? メインフレームと端末
利用者は地理的に分散(distributed)しているが、プログラムは、すべて中央の1台のコン ピュータで動作する。文字端末の役目
「端末」は、メインフレーム(ホスト)と文字回線で接続されている。 電話回線等を使ったモデムによる接続。2400bps-9600bps。 IBMのものは、半二重。
図? 集中型システムのハードウェアとOS
ハードウェアやオペレーティング・システムの働きで、次のようなことが(あ る程度のレベルで簡単に)実現できる。
Process1() { write(file1,buf,bytes); ... ... } |
Process2() { ... ... read(file1,buf,bytes); } |
Process3() { ... ... read(file1,buf,bytes); } |
図? 共有メモリ型マルチプロセッサ(バス共有)
図? LANに接続されたPC
遠隔のメモリは、アクセスできない(no remote memory access)。 機種が違うこともある。交通機関 | ネットワーク |
---|---|
徒歩 4km/h | 64kbps 電話回線 |
自動車 40km/h | 640kbps ADSL(低速) |
飛行機 800km/h | イーサネット(10Mbps), ADSL(中速), 無線LAN |
人工衛星(第一宇宙速度) 28440km/h | 450Mbps, イーサネット(100Mbps-10Gbps) |
最後の性質が大事である。
構成要素の数が増えた時にどうなるか。 10台で動くものが100台、1000台で動くか。
実用になり、かつ、利益に見合うコストで実現できる範囲を探すことが大事になる。
図? 単一のコンピュータでハイスコアをファイルに保存
ライブラリの機能int get_highscore(score_record_t records[], int len)
score_record_t
型)を最大 len
個だけ取得する。
実際に保存していた数を返す。
int put_score(int score, char *user)
.
」を忘れないように。
% mkdir hiscore-c
% cd hiscore-c
% cp ~yas/dsys/highscore/centralized/highscore.h .
% cp ~yas/dsys/highscore/centralized/highscore.c .
% cp ~yas/dsys/highscore/centralized/add-hiscore.c .
% cp ~yas/dsys/highscore/centralized/show-hiscore.c .
% cp ~yas/dsys/highscore/centralized/Makefile .
% ls
Makefile add-hiscore.c highscore.c highscore.h show-hiscore.c
% make
cc -g -c -o add-hiscore.o add-hiscore.c
cc -g -c -o highscore.o highscore.c
cc -g add-hiscore.o highscore.o -o add-hiscore
cc -g -c -o show-hiscore.o show-hiscore.c
cc -g show-hiscore.o highscore.o -o show-hiscore
% ls
Makefile add-hiscore.c highscore.c highscore.o show-hiscore.c
add-hiscore add-hiscore.o highscore.h show-hiscore show-hiscore.o
%
make
コマンドを実行すると、Makefile
の記述に従い2つの実行
形式のファイル add-hiscore
と add-hiscore
が作られる。
例題を実行するには、環境変数 hiscoredata
にファイル名を
設定する。その方法は、make help
で表示される。
% make help
setenv hiscoredata `mktemp /tmp/coins-dsys-XXXXXXXXXX`
ls -l $hiscoredata
./add-hiscore score name
./show-hiscore num
rm $hiscoredata
%
help に従い、/tmp の下に予測が困難なファイル名でデータファイルを
作成する。(ホーム・ディスクの下に作成した場合は、うまく動作しない。理由
は後述。)
mktemp
コマンドを実行し、その出力で、
環境変数 hiscoredata
を設定する。
% setenv hiscoredata `mktemp /tmp/coins-dsys-XXXXXXXXXX`
% printenv hiscoredata
/tmp/coins-dsys-8ofae8kMu4
% echo $hiscoredata
/tmp/coins-dsys-8ofae8kMu4
% ls -l $hiscoredata
-rw------- 1 yas wheel 0 Nov 30 20:10 /tmp/coins-dsys-8ofae8kMu4
%
この例では、mktemp
コマンドは、
/tmp/coins-dsys-8ofae8kMu4
というファイルを
作成し、そのファイル名を標準出力に出力する。
実験が終了したら rm
コマンドで削除すること。
バッククォート(` `
は、シェルの文法で、
コマンドの出力をコマンド行に持ってくる。上の例では、以下のコマンドと同
じである。
% setenv hiscoredata /tmp/coins-dsys-8ofae8kMu4
環境変数は、csh の組み込みコマンド printenv で表示できる。
シェルでは、$
をつけて参照することもできる。
プログラムの中では、getenv()
ライブラリ関数で参照できる。
環境変数 hiscoredata
を設定した後は、add-hiscore
コマンド
と show-hiscore
を実行することができる。
% ./add-hiscore 10 "Yasushi Shinjo"
% ls -l $hiscoredata
-rw------- 1 yas wheel 32 Nov 30 20:11 /tmp/coins-dsys-8ofae8kMu4
% ./show-hiscore 10
10 Yasushi Shinjo
% ./add-hiscore 20 "Kazuhiko Kato"
% ./show-hiscore 10
20 Kazuhiko Kato
10 Yasushi Shinjo
% ls -l $hiscoredata
-rw------- 1 yas wheel 64 Nov 30 20:24 /tmp/coins-dsys-8ofae8kMu4
%
実験が終了したら、rm
コマンドで削除する。
% ls -l $hiscoredata
-rw------- 1 yas wheel 64 Nov 30 20:24 /tmp/coins-dsys-8ofae8kMu4
% rm $hiscoredata
%
get_highscore()
関数を呼び出す簡単なプログラム。
[show-hiscore.c]
1: 2: /* 3: show-hiscore.c -- The main function for get_highscore(). 4: Created on: 2008/11/28 18:40:56 5: ~yas/dsys/highscore/centralized/show-hiscore.c 6: */ 7: 8: #include <stdio.h> /* stderr, fprintf() */ 9: #include <stdlib.h> /* strtol() */ 10: #include "highscore.h" 11: 12: static void show_score( int top ); 13: 14: static void usage( char *comname ) { 15: fprintf(stderr,"Usage: %% %s n\n", comname); 16: exit( 1 ); 17: } 18: 19: main( int argc, char *argv[], char *envp[] ) { 20: int top; 21: char *name ; 22: if( argc != 2 ) 23: usage( argv[0] ); 24: top = strtol( argv[1], 0, 10); 25: show_score( top ); 26: } 27: 28: static void show_score( int top ) { 29: score_record_t records[HIGHSCORE_MAX_RECORDS]; 30: int n, i ; 31: if( top > HIGHSCORE_MAX_RECORDS ) { 32: fprintf(stderr,"Warning: top too large: %d\n",top); 33: top = HIGHSCORE_MAX_RECORDS; 34: } 35: n = get_highscore( records, top ); 36: for( i=0; i<n; i++ ) { 37: printf("%10d %s\n", records[i].score, records[i].name ); 38: } 39: }
get_highscore()
関数を呼び出す。
put_score()
関数を呼び出す簡単なプログラム。
[add-hiscore.c]
1: 2: /* 3: add-hiscore.c -- The main function of put_score(). 4: Created on: 2008/11/28 17:22:21 5: ~yas/dsys/highscore/centralized/add-hiscore.c 6: */ 7: 8: #include <stdio.h> /* stderr, fprintf() */ 9: #include <stdlib.h> /* strtol() */ 10: #include "highscore.h" 11: 12: void usage( char *comname ) { 13: fprintf(stderr,"Usage: %% %s score \"User Name\"\n", comname); 14: exit( 1 ); 15: } 16: 17: main( int argc, char *argv[], char *envp[] ) { 18: int score ; 19: char *name ; 20: if( argc != 3 ) 21: usage( argv[0] ); 22: score = strtol( argv[1], 0, 10); 23: name = argv[2]; 24: put_score( score, name ); 25: }
put_score()
関数を呼び出す。
1: 2: /* 3: highscore.h -- Hiscore Library for centralized systems. 4: Created on: 2008/11/28 11:49:18 5: ~yas/dsys/highscore/centralized/highscore.h 6: */ 7: 8: #ifndef _HIGHSCORE_LIB_CENTRALIZED_H_ 9: #define _HIGHSCORE_LIB_CENTRALIZED_H_ 10: 11: #define HIGHSCORE_MAX_RECORDS 10 12: #define HIGHSCORE_NAME_LEN 28 13: #define HIGHSCORE_FILE_ENV "hiscoredata" 14: 15: struct score_record { 16: int score; 17: char name[HIGHSCORE_NAME_LEN]; 18: }; 19: typedef struct score_record score_record_t; 20: 21: extern int get_highscore(score_record_t records[], int len); 22: extern put_score(int score, char *user); 23: 24: #endif _HIGHSCORE_LIB_CENTRALIZED_H_
score_record_t
で表現する。
この構造体は、全体で32バイトある。の最初の4バイトは、整数型で、得点、残
りの28バイトは、文字の配列。ASCII で最大27文字まで保存できる。文字が含
まれない部分は、0が入る。
score_record_t
型の配列で表す。
hiscoredata
に設定する。
1: 2: /* 3: highscore-lib-centralized.c -- Hiscore Library for centralized systems. 4: Created on: 2008/11/28 11:45:58 5: ~yas/dsys/highscore/centralized/highscore-lib-centralized.c 6: */ 7: 8: #include <fcntl.h> /* open() */ 9: #include <sys/types.h> /* fstat() */ 10: #include <sys/stat.h> /* fstat() */ 11: #include <string.h> /* memcpy(), memset() */ 12: #include <stdio.h> /* snprintf(), perror() */ 13: #include <stdlib.h> /* getenv() */ 14: #include <sys/file.h> 15: 16: #include "highscore.h" 17: 18: static int insert_score( score_record_t records[], int len, int nelement, 19: int score, char *user ); 20: static int find_posision( score_record_t records[], int len, int nelement, 21: int score ); 22:
23: int get_highscore(score_record_t records[], int len) { 24: int fd; 25: struct stat stat; 26: ssize_t bytes; 27: char *filename; 28: 29: if( (filename=getenv(HIGHSCORE_FILE_ENV)) == NULL ) { 30: fprintf(stdout,"No environment: %s\n",HIGHSCORE_FILE_ENV ); 31: return( 0 ); 32: } 33: if( (fd = open(filename,O_RDONLY)) < 0 ) { 34: perror( filename ); 35: return( 0 ); 36: } 37: if( flock(fd,LOCK_SH) < 0 ) { 38: perror("flock"); 39: goto error0; 40: } 41: if( fstat(fd,&stat) < 0 ) { 42: perror("fstat"); 43: goto error1; 44: } 45: bytes = (stat.st_size <= len*sizeof(score_record_t)) ? 46: stat.st_size : len*sizeof(score_record_t) ; 47: if( read(fd, records, bytes)!=bytes ) { 48: perror("read"); 49: goto error1; 50: } 51: if( flock(fd,LOCK_UN) < 0 ) { 52: perror("flock"); 53: goto error0; 54: } 55: close( fd ); 56: return( bytes/sizeof(score_record_t) ); 57: 58: error1: flock( fd,LOCK_UN ); 59: error0: close( fd ); 60: return( 0 ); 61: } 62:
hiscoredata
(HIGHSCORE_FILE_ENV
) から
ファイル名を取得する。
O_RDONLY
で開く。
LOCK_SH
)でロックする。
fstat()
で調べる。
LOCK_SH
(shared lock または read lock)
LOCK_EX
(exclusive lock または write lock)
図? 普通のロックと読み書きロック
注意: 最近では、flock() ではなくて、fcntl() を使うのが一般的。 fcntl() では、ファイルの一部をロックできる。63: int put_score(int score, char *user) { 64: int fd, n; 65: struct stat stat; 66: ssize_t bytes; 67: off_t offset ; 68: score_record_t records[HIGHSCORE_MAX_RECORDS]; 69: char *filename; 70: 71: if( (filename=getenv(HIGHSCORE_FILE_ENV)) == NULL ) { 72: fprintf(stdout,"No environment: %s\n",HIGHSCORE_FILE_ENV ); 73: return( 0 ); 74: } 75: if( (fd = open( filename,O_RDWR|O_CREAT, 0666)) < 0 ) { 76: perror( filename ); 77: return( 0 ); 78: } 79: if( flock(fd,LOCK_EX) < 0 ) { 80: perror("flock"); 81: goto error0; 82: } 83: if( fstat(fd,&stat) < 0 ) { 84: perror("fstat"); 85: goto error1; 86: } 87: bytes = (stat.st_size <= HIGHSCORE_MAX_RECORDS*sizeof(score_record_t))? 88: stat.st_size : HIGHSCORE_MAX_RECORDS*sizeof(score_record_t) ; 89: if( read(fd, records, bytes)!=bytes ) { 90: perror("read"); 91: goto error1; 92: } 93: 94: n = insert_score( records,HIGHSCORE_MAX_RECORDS,bytes/sizeof(score_record_t), 95: score, user ); 96: 97: if( n > 0 ) { 98: offset = 0L; 99: if( lseek( fd, offset, SEEK_SET )< 0 ) { 100: perror("lseek"); 101: goto error1; 102: } 103: bytes = n * sizeof(score_record_t); 104: if( write(fd, records, bytes)!=bytes ) { 105: perror("write"); 106: goto error1; 107: } 108: } 109: 110: if( flock(fd,LOCK_UN) < 0 ) { 111: perror("flock"); 112: goto error1; 113: } 114: close( fd ); 115: return( 1 ); 116: 117: error1: flock( fd,LOCK_UN ); 118: error0: close( fd ); 119: return( 0 ); 120: } 121:
hiscoredata
(HIGHSCORE_FILE_ENV
) から
ファイル名を取得する。
O_RDWR
(read-write) で開く。
LOCK_EX
)でロックする。
fstat()
で調べる。
insert_score()
)。
122: static int insert_score( score_record_t records[], int len, int nelement, 123: int score, char *user ) { ... 140: static int find_posision( score_record_t records[], int len, int nelement, 141: int score ) { ...
insert_score()
は、スコアの配列に、要素を追加する。先頭が一
番高得点になるようにソートして入れる。空きがない場合には、一番小さなス
コアの場所をつぶす。
find_posision()
は、ソートされた配列でどの場所に要素を挿入
すればよいかを探す。
[Makefile]
注意:r系コマンドは、ネットワーク上を生パスワードが流れて危険なので、使われない。 その代わりに、ssh, slogin, scp が使われる。
現在、広く使われているオペレーティング・システムで、 ネットワーク通信機能があるものは、これに分類される。
図? ネットワークOSでのアプリケーションの実行
目標
分散OSの種類
図? 分散OSでのアプリケーションの実行
種類
図? ミドルウェアを用いた分散アプリケーションの実行
どこまで隠せば分散型プログラミング言語と呼んでもよいか? 「socket があれば、分散型プログラミング言語」とは、定義したくない。 永続言語との比較。