システム・プログラムI 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro1-1997/1997-05-20
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html
---------------------------------------------------------------------- 1: /* 2: arg-print.c -- mainの引数を表示するプログラム 3: /usr/local/LECTURES/syspro-1997-shinjo/env/arg-print.c 4: $Header: arg-print.c,v 1.3 97/05/19 22:40:45 yas Exp $ 5: Start: 1997/04/21 18:23:13 6: */ 7: 8: main( argc,argv ) 9: int argc ; 10: char *argv[] ; 11: { 12: int i ; 13: printf("argc == %d\n", argc ); 14: printf("argv == 0x%x\n",argv ); 15: for( i=0 ; argv[i] ; i++ ) 16: printf("argv[%d]==0x%x, \"%s\"\n",i,argv[i],argv[i] ); 17: } ----------------------------------------------------------------------実行例。
---------------------------------------------------------------------- % ./arg-print a bbb "c c"argc == 4 argv == 0x7b0333f8 argv[0]==0x7b033000, "./arg-print" argv[1]==0x7b03300c, "a" argv[2]==0x7b03300e, "bbb" argv[3]==0x7b033012, "c c" %
----------------------------------------------------------------------
---------------------------------------------------------------------- 1: /* 2: env-print.c -- 環境変数を表示するプログラム 3: /usr/local/LECTURES/syspro-1997-shinjo/env/env-print.c 4: $Header: env-print.c,v 1.2 97/05/19 22:44:46 yas Exp $ 5: Start: 1997/05/05 16:42:22 6: */ 7: extern char **environ ; 8: 9: main( argc,argv,envp ) 10: int argc ; 11: char *argv[] ; 12: char *envp[] ; 13: { 14: int i ; 15: printf("envp == 0x%x\n",envp ); 16: for( i=0 ; envp[i] ; i++ ) 17: printf("envp[%d]==0x%x, \"%s\"\n",i,envp[i],envp[i] ); 18: printf("environ == 0x%x\n",environ ); 19: for( i=0 ; environ[i] ; i++ ) 20: printf("environ[%d]==0x%x, \"%s\"\n",i,environ[i],environ[i] ); 21: } ----------------------------------------------------------------------実行例。
---------------------------------------------------------------------- % ./env-printenvp == 0x7b0333f8 envp[0]==0x7b03300c, "DISPLAY=top:0.0" envp[1]==0x7b03301c, "HOME=/home/lab2/OS/yas" envp[2]==0x7b033033, "HOST=orchid" ... envp[24]==0x7b0333e1, "MORE=-d" environ == 0x7b0333f8 environ[0]==0x7b03300c, "DISPLAY=top:0.0" environ[1]==0x7b03301c, "HOME=/home/lab2/OS/yas" environ[2]==0x7b033033, "HOST=orchid" ... environ[24]==0x7b0333e1, "MORE=-d" %
----------------------------------------------------------------------
---------------------------------------------------------------------- 1: /* 2: vaddr-print.c -- 変数の番地をしらべるプログラム 3: /usr/local/LECTURES/syspro-1997-shinjo/env/vaddr-print.c 4: $Header: vaddr-print.c,v 1.1 97/05/19 23:19:10 yas Exp $ 5: Start: 1997/05/19 22:58:49 6: */ 7: #include <stdlib.h> 8: 9: int x1=1 ; 10: int x2 ; 11: 12: extern int etext, edata, end ; 13: 14: main( argc,argv,envp ) 15: int argc ; 16: char *argv[] ; 17: char *envp[] ; 18: { 19: int x3 ; 20: char *x4p ; 21: 22: printf("&main == 0x%x \n",&main ); 23: printf("&etext == 0x%x \n",&etext ); 24: printf("&edata == 0x%x \n",&edata ); 25: printf("&end == 0x%x \n",&end ); 26: 27: printf("&x1 == 0x%x (data)\n",&x1 ); 28: printf("&x2 == 0x%x (bss)\n",&x2 ); 29: printf("&x3 == 0x%x (auto)\n",&x3 ); 30: x4p = malloc( 10 ); 31: printf("x4p == 0x%x (heap)\n",x4p ); 32: x4p = malloc( 10 ); 33: printf("x4p == 0x%x (heap)\n",x4p ); 34: recursive( 3 ); 35: } 36: 37: recursive( n ) 38: int n ; 39: { 40: int x5 ; 41: printf("&x5 == 0x%x (auto,%d)\n",&x5,n ); 42: if( n<=0 ) 43: return; 44: recursive( n-1 ); 45: } ----------------------------------------------------------------------実行例。
---------------------------------------------------------------------- % ./vaddr-print&main == 0x400012ea &etext == 0x24c8 &edata == 0x40001310 &end == 0x40001528 &x1 == 0x400012a0 (data) &x2 == 0x40001524 (bss) &x3 == 0x7b0335b8 (auto) x4p == 0x40003530 (heap) x4p == 0x40003548 (heap) &x5 == 0x7b0335f8 (auto,3) &x5 == 0x7b033638 (auto,2) &x5 == 0x7b033678 (auto,1) &x5 == 0x7b0336b8 (auto,0) % size ./vaddr-print
5318 + 780 + 536 = 6634 % size -x ./vaddr-print
14c6 + 30c + 218 = 0x19ea %
----------------------------------------------------------------------
malloc() は、brk() システム・コール、または、sbrk システム・コールでオ ペレーティング・システムからメモリの割り当てを受けている。brk(), sbrk() は、プロセスのデータ・セグメントの終わりを変化させるシステム・ コールである。
いままで作ってきたファイル入力を行うプログラムを、mmap() を使って書き 換えなさい。そして、それらの比較しなさい。mmap() 使うものは、malloc() して read() するのとどこが違うか。どういう場合には、どういう観点でどれ がよいかを論じなさい。
UNIX では、新たにプロセスを作る時に、自分のコピーしか作れない(fork()シ ステム・コール)。元のプロセスを親プロセス、作られたプロセスを子プロセ スという。
現在のプログラムの実行はそのまま続けて、新しくプログラムを実行するには、 次のようにする。
---------------------------------------------------------------------- 1: /* 2: proc-create.c -- calプログラムよりプロセスを作る 3: /usr/local/LECTURES/syspro-1997-shinjo/proc/proc-create.c 4: $Header: proc-create.c,v 1.2 97/05/19 23:58:59 yas Exp $ 5: Start: 1995/02/27 15:27:54 6: */ 7: 8: #include <unistd.h> /* pid_t */ 9: 10: extern char **environ; 11: 12: main() 13: { 14: pid_t child_pid ; 15: if( (child_pid=fork()) == 0 ) 16: { 17: char *argv[4] ; 18: printf("child: pid == %d, ppid == %d\n", getpid(), getppid() ); 19: argv[0] = "cal" ; 20: argv[1] = "5" ; 21: argv[2] = "1997" ; 22: argv[3] = 0 ; 23: execve( "/usr/bin/cal", argv, environ ); 24: perror( "execve" ); 25: /* exec に失敗したら exit() を忘れないこと */ 26: exit( 1 ); 27: } 28: else if( child_pid > 0 ) 29: { 30: printf("parent: pid == %d, ppid == %d, child_pid == %d\n", 31: getpid(), getppid(),child_pid ); 32: } 33: else 34: { 35: perror("fork"); 36: } 37: } ----------------------------------------------------------------------実行例。
execve() は、システム・コールである。これを使いやすくするために、次の ようなライブラリ関数が用意されている。---------------------------------------------------------------------- % ./proc-createchild: pid == 24942, ppid == 24941 parent: pid == 24941, ppid == 14800, child_pid == 24942 % May 1997 S M Tu W Th F S 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
%
----------------------------------------------------------------------
int execl(const char *path, const char *arg0, ..., const char *argn, char * /*NULL*/); int execv(const char *path, char *const argv[]); int execle (const char *path,char *const arg0[], ... , const char *argn, char * /*NULL*/, char *const envp[]); int execve (const char *path, char *const argv[], char *const envp[]); int execlp (const char *file, const char *arg0, ..., const char *argn, char * /*NULL*/); int execvp (const char *file, char *const argv[]); int system(const char *string); FILE *popen(const char *command, const char *type); int pclose (FILE *stream);
上の実行結果では、親プロセスの出力と子プロセスの出力が入り交じっている。 この理由を考えなさい。
この問題を解決しなさい。そのためには、wait() システム・コール (waitpid(),wait3(),wait4()など)を用いて、同期を行えばよい。すなわち、 子プロセスが表示する可能性がある間は、親プロセスを待ち状態にしなさい。