プロセスのメモリ

システム・プログラム

                                       電子・情報工学系
                                       新城 靖
                                       <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言語でプログラムを書く時には、必ずメモリの中でどのような操 作が行われているかを意識すること。

■メモリ・マップ

図? のように, Unixのプロセスのメモリは、はテキストセグメント, データセグメ ント, スタックセグメントに分類される。ここでセグメントとは、連続した メモリの領域のことである。

図? プロセスのアドレス空間

図? プロセスのアドレス空間

◆テキストセグメント

 機械語命令を置くためのセグメンを テキスト・セグメント ( text segment, ) という。このセグメントは、普通、読み出し専用になっていて, 同じロードモ ジュールのプロセスの間で共有される。例えばシェルは複数のユーザが同時に 使うことが多いが、この場合、テキストセグメントのためのメモリは1セット だけでよい。

機械語を書き換えながら実行するプログラムは、最近は行儀が悪いとされてい る。キャッシュの関係で特別な操作をしないと動かない。

◆データセグメント

データ・セグメント ( data segment, ) は、データを置く領域である. C言語の 静的変数(static)大域変数(extern) malloc() で割り当てたヒープ上の変数は、 このセグメントに置かれます。 ( 自動変数(auto) は、次のスタック・セグメントに置かれる。 )  データセグメントは, 次の3つにわかれています.
データ
静的変数や大域変数のうち、初期値つき変数が置かれるところ
BSS
静的変数や大域変数のうち、初期値を指定しない(初期値が0)が置かれるところ
ヒープ(heap) malloc() で確保する変数が置かれるところ
 データの初期値は、実行形式ファイルに含まれている. 例えばC言語で

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() ライブラリ関数から呼び出さ れる。

◆スタックセグメント

スタック・セグメント ( stack segment, ) とはスタックを置くためのメモリ領域である。C言語の 自動変数(auto variable)、 変数は, ここに置かれる.

 C言語で


main()
{
    auto int z;
}
とすると, 4バイトの領域がスタックセグメントに割りつけられる。 (autoというキーワードは、普通省略される。スタックセグメ ントは、普通、0xffffff (32ビットのアドレス空間の場合)からからアドレス が小さくなるほうに向かって伸びていく。この部分は、関数呼び出しが続くと 伸びていき、割り当てられたメモリよりも多くなると、カーネルが自動的に拡 張する。

◆mainの引数と環境変数

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

■mainの引数


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

★練習問題

★練習問題8 printfの番地

printf 関数の番地を調べなさい。

★練習問題9 引数の番地

関数の引数の番地を調べなさい。auto変数と比較しなさい。
↑[もどる] ・[4月17日] →[4月24日]
Last updated: 2000/04/16 20:05:49
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>