システム・プログラム
電子・情報工学系
新城 靖
<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言語で
char *p ;
...
p = malloc( 100 );
とすると100バイトの領域がヒープ上に確保される。
ヒープ領域の大きさは、brk() システム・コールや
sbrk() システム・コールで変えることができる。これらの
システム・コールは、malloc() ライブラリ関数から呼び出さ
れる。
C言語で
main()
{
auto int z;
}
とすると, 4バイトの領域がスタックセグメントに割りつけられる。
(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 %
----------------------------------------------------------------------