システム・プログラム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()など)を用いて、同期を行えばよい。すなわち、 子プロセスが表示する可能性がある間は、親プロセスを待ち状態にしなさい。