システム・プログラム 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro-2000/2000-04-17
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html
この授業でC言語でプログラムを書く時には、必ずメモリの中でどのような操 作が行われているかを意識すること。
図? プロセスのアドレス空間
機械語命令を置くためのセグメンを テキスト・セグメント ( text segment, ) という。このセグメントは、普通、読み出し専用になっていて, 同じロードモ ジュールのプロセスの間で共有される。例えばシェルは複数のユーザが同時に 使うことが多いが、この場合、テキストセグメントのためのメモリは1セット だけでよい。機械語を書き換えながら実行するプログラムは、最近は行儀が悪いとされてい る。キャッシュの関係で特別な操作をしないと動かない。
データ・セグメント ( data segment, ) は、データを置く領域である. C言語の 静的変数(static)、 大域変数(extern)malloc()
で割り当てたヒープ上の変数は、
このセグメントに置かれます。
(
自動変数(auto)
は、次のスタック・セグメントに置かれる。
)
データセグメントは, 次の3つにわかれています.
malloc()
で確保する変数が置かれるところ
と書くとstatic int x=100 ;
x
はデータセグメントに割りつけられ,
実行形式ファイルに100という整数のビットパタンが含まれる。
BSSとは初期値を指定しない変数が置かれる場所である. C言語で
と書くとstatic int x ;
y
はBSSに割りつけられる。実行形式のファイルに
は、BSSの領域はない。これは実行時にカーネルが領域を割り当て、内容
を0に初期化します。
ヒープとは実行時に大きさが決まる変数を置くための領域である. C言語で
とすると100バイトの領域がヒープ上に確保される。char *p ; ... p = malloc( 100 );
ヒープ領域の大きさは、brk()
システム・コールや
sbrk()
システム・コールで変えることができる。これらの
システム・コールは、malloc()
ライブラリ関数から呼び出さ
れる。
C言語で
とすると, 4バイトの領域がスタックセグメントに割りつけられる。 (main() { auto int z; }
auto
というキーワードは、普通省略される。スタックセグメ
ントは、普通、0xffffff (32ビットのアドレス空間の場合)からからアドレス
が小さくなるほうに向かって伸びていく。この部分は、関数呼び出しが続くと
伸びていき、割り当てられたメモリよりも多くなると、カーネルが自動的に拡
張する。
UNIXではプログラムを実行するときに,
引数(argument)
と
環境変数(environment variable)
が渡される。
C言語では、次のようにmain()
関数が3つの引数で呼び出される
ようになっている。
ここで、main( int argc, char *argv[], *envp[] ) { }
argc
が、引数の数(argv
の数) ,
argv
が、引数のベクタの先頭番地、
envp
が環境変数のベクタの先頭番地である。この引数と環境変数は、スタックセグ
メントのスタックの底、
図?
では上(アドレスが大きいところ)にある。
共有ライブラリは、ヒープとスタック・セグメントの間にある。 どの番地に割り当てられるかは、システムに依存する。
---------------------------------------------------------------------- 1: /* 2: vaddr-print.c -- 変数の番地をしらべるプログラム 3: ~yas/syspro1/cc/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: } ----------------------------------------------------------------------実行例。
---------------------------------------------------------------------- % cp ~yas/syspro1/cc/vaddr-print.c . % make vaddr-print cc vaddr-print.c -o vaddr-print % ./vaddr-print &main == 0x400ad0 &etext == 0x400cb0 &edata == 0x10002000 &end == 0x10002000 &x1 == 0x100010d0 (data) &x2 == 0x10001130 (bss) &x3 == 0x7fff2f1c (auto) x4p == 0x10002010 (heap) x4p == 0x10002028 (heap) &x5 == 0x7fff2ef4 (auto,3) &x5 == 0x7fff2ecc (auto,2) &x5 == 0x7fff2ea4 (auto,1) &x5 == 0x7fff2e7c (auto,0) % size vaddr-print text data bss dec hex filename 2933 304 28 3265 cc1 vaddr-print % ----------------------------------------------------------------------
---------------------------------------------------------------------- 1: /* 2: arg-print.c -- mainの引数を表示するプログラム 3: ~yas/syspro1/cc/arg-print.c 4: $Header: arg-print.c,v 1.2 97/04/21 18:29:06 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 is %d\n", argc ); 14: for( i=0 ; i<argc ; i++ ) 15: printf("argv[%d]: %s\n",i,argv[i] ); 16: } ----------------------------------------------------------------------実行例。
---------------------------------------------------------------------- % cp ~yas/syspro1/cc/arg-print.c . % make arg-print cc arg-print.c -o arg-print % ./arg-print argc is 1 argv[0]: ./arg-print % ./arg-print who am i argc is 4 argv[0]: ./arg-print argv[1]: who argv[2]: am argv[3]: i % ----------------------------------------------------------------------