実行環境、プロセスの生成

システム・プログラム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

■復習

■mainの引数


----------------------------------------------------------------------
   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"
% []
----------------------------------------------------------------------

★練習問題(10) echoコマンド

echo コマンドと似た動きをするプログラムを作りなさい。

■環境変数


----------------------------------------------------------------------
   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-print  [←]
envp == 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"
% []
----------------------------------------------------------------------

★練習問題(11) printenvコマンド

printenv コマンドと似た動きをするプログラムを作りなさい。

★練習問題(12) getenv()の利用

getenv() ライブラリ関数を利用して環境変数を得なさい。

★練習問題(13) putenv()の利用

setenv() ライブラリ関数を利用して環境変数を変え、プログラムの動き(ラ イブラリ関数の動き)が変ることを確かめなさい。

★練習問題(14) getenv()の実現

getenv() ライブラリ関数と似た動きをする関数を作りなさい。

★練習問題(15) putenv()の利用

putenv() ライブラリ関数と似た動きをする関数を作りなさい。

■変数の番地、メモリ・マップ


----------------------------------------------------------------------
   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
% []
----------------------------------------------------------------------

★練習問題(16) malloc()、freeの仕組み

malloc() と free() の動きを調べなさい。 malloc() と free() の動きから、その仕組みを想像しなさい。

malloc() は、brk() システム・コール、または、sbrk システム・コールでオ ペレーティング・システムからメモリの割り当てを受けている。brk(), sbrk() は、プロセスのデータ・セグメントの終わりを変化させるシステム・ コールである。

■mmap

ファイルを、プロセスが持っているアドレス空間にに張り付ける (マップする)機能がある。

★練習問題(17) mmap

いままで作ってきたファイル入力を行うプログラムを、mmap() を使って書き 換えなさい。そして、それらの比較しなさい。mmap() 使うものは、malloc() して read() するのとどこが違うか。どういう場合には、どういう観点でどれ がよいかを論じなさい。

■プロセスの生成とプログラムの実行

UNIX では、新たにプロセスを作る時に、自分のコピーしか作れない(fork()シ ステム・コール)。元のプロセスを親プロセス、作られたプロセスを子プロセ スという。

現在のプログラムの実行はそのまま続けて、新しくプログラムを実行するには、 次のようにする。

execve() システム・コールの引数は、main() の引数と関連している。


----------------------------------------------------------------------
   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:	}
----------------------------------------------------------------------

実行例。

----------------------------------------------------------------------
 % ./proc-create [←]
 child: 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

 [←]
 % []
----------------------------------------------------------------------

execve() は、システム・コールである。これを使いやすくするために、次の ようなライブラリ関数が用意されている。
     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);

★練習問題(18) waitシステム・コール

上の実行結果では、親プロセスの出力と子プロセスの出力が入り交じっている。 この理由を考えなさい。

この問題を解決しなさい。そのためには、wait() システム・コール (waitpid(),wait3(),wait4()など)を用いて、同期を行えばよい。すなわち、 子プロセスが表示する可能性がある間は、親プロセスを待ち状態にしなさい。

★[report] report-6,malloc()/mmap()/wait()

練習問題(16),(17),(18) の中から1つ以上選んでやりなさい。問題を難しい 方に変更してもよい。(印刷した資料では、report-5になっていました。)
↑[もどる] ←[5月13日] ・[5月20日] →[5月27日]
Last updated: 1997/05/20 01:09:11
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>