コマンド引数と環境変数


Rev.3を表示中。最新版はこちら

環境変数は子プロセスへ引き継がれていく。すなわち各プロセス間で環境変を管理している。シェルからプロセスを起動すると、最終的にコマンド引数と環境変数を引数に取るdo_execveが呼ばれる。(シェルで環境変数としてexportはシェルが管理していて、シェルプロセスとしてこの変数が環境変数に設定されるわけでない。)

そして、引数のコマンド引数および環境変数を、カーネルがアロケートしたstruct linux_binprm構造体内のページに複写し、それをプロセスのスタックエリアに持ってこれるようにリニアアドレスを調整すべきページテーブルを変更し、最後にスタックをその領域分拡張することで、コマンド引数と環境変数を子プロセスのスタック上に継承させているようだ。(たぶん、たぶん、たぶんん・・・・)

したがって、子プロセスはそのスタックからコマンド引数と環境変数を取得することが可能となる。ことの時の設定されたスタックは、スタックトップからコマンド数、コマンド変数1のアドレス・・・コマンド変数nのアドレス、デリミターとしての0、環境変数1のアドレス・・・環境変数nのアドレスとなり、以降に実際のコマンド引数群と環境変数群が設定されていく。

簡単なCのプログラムを-gオプションでコンパイルし、gdb下でまず_startにブレイクしてその時点までrunした後のスタックの内容を確認してみる。
a.c
#include "stdio.h"

main(int argc, char* argv[])
{
   printf("%x\n", &argc);
}

[root@localhost kitamura]# gcc a.c -g
[root@localhost kitamura]# gdb a.out
(gdb) set arg aaa bbb                <- コマンド引数 aaa,bbbをセット
(gdb) b _start                       <- _startにブレイクポイント
(gdb) b main                         <- main()にブレイクポイント
(gdb) r <-実行
Starting program: /home/kitamura/a.out aaa bbb

スタックのトップからの内容である。まず3はargcで、続いてargv[0],argv[1],argv[2]その次がデリミタターとしての0で、以降環境変数のポインタが続いている。
(gdb) x/20 $esp
0xbffff7d0:     0x00000003      0xbffff8fd      0xbffff912      0xbffff916
0xbffff7e0:     0x00000000      0xbffff91a      0xbffff939      0xbffff949
0xbffff7f0:     0xbffff954      0xbffff962      0xbffff982      0xbffff998
0xbffff800:     0xbffff9b6      0xbffff9c9      0xbffff9d3      0xbffffe14
0xbffff810:     0xbffffe20      0xbffffea5      0xbffffebf      0xbffffece

argv[0]以降をダンプしてみると、上のアドレスに従ってコマンド変数と環境変数が続いている。
(gdb) x/20 $esp                      <- _startのスタックargc,argv[0],argv[1],argv[2],9,ebv[0]...
0xbffff7d0:     0x00000003      0xbffff8fc      0xbffff911      0xbffff915
0xbffff7e0:     0x00000000      0xbffff919      0xbffff938      0xbffff948
0xbffff7f0:     0xbffff953      0xbffff961      0xbffff982      0xbffff998
0xbffff800:     0xbffff9b6      0xbffff9c9      0xbffff9d3      0xbffffe14
0xbffff810:     0xbffffe1f      0xbffffea4      0xbffffebe      0xbffffecd
(gdb) x/40s 0xbffff8fc               <- argv[0]以降の内容
0xbffff8fc:      "/home/kitamura/a.out"
0xbffff911:      "aaa"
0xbffff915:      "bbb"
0xbffff919:      "HOSTNAME=localhost.localdomain"
0xbffff938:      "SHELL=/bin/bash"
 :
0xbffffecd:      "PWD=/home/kitamura"
0xbffffee0:      "INPUTRC=/etc/inputrc"
0xbffffef5:      "LANG=ja_JP.eucJP"
 :

Cのmain関数はglibがこのスタックから必要な変数を再度スタックに積んでmainをコールすることになる。
(gdb) c                               <- コンティニュー
Continuing.

Breakpoint 2, main (argc=3, argv=0xbffff7d4) at a.c:5
5               printf("%x\n", &argc);
(gdb)                                  <- ステップ実行でargcのアドレスの確認
bffff750
6       }

(gdb) x/60x $esp                      <- その時のスタック内容
0xbffff720:     0x080484b4      0xbffff750      0xbffff748      0x08048419
0xbffff730:     0x00ae06d0      0xbffff750      0xbffff7a8      0x00b0b6e5
0xbffff740:     0x08048400      0x08048310      0xbffff7a8      0x00b0b6e5
0xbffff750:     0x00000003      0xbffff7d4      0xbffff7e4      0xb7ff02d8 <- main(argc, argv[])
0xbffff760:     0x00000001      0x00000001      0x00000000      0x0804822c
0xbffff770:     0x00c64ff4      0x08048400      0x08048310      0xbffff7a8
0xbffff780:     0x742bf9b5      0xeaa80ccb      0x00000000      0x00000000
0xbffff790:     0x00000000      0x00ae6530      0x00b0b60d      0x00af1fc0
0xbffff7a0:     0x00000003      0x08048310      0x00000000      0x08048331
0xbffff7b0:     0x080483c4      0x00000003      0xbffff7d4      0x08048400
0xbffff7c0:     0x080483f0      0x00ae06d0      0xbffff7cc      0x00000000
0xbffff7d0:     0x00000003      0xbffff8fc      0xbffff911      0xbffff915 <- カーネルがセット
0xbffff7e0:     0x00000000      0xbffff919      0xbffff938      0xbffff948
0xbffff7f0:     0xbffff953      0xbffff961      0xbffff982      0xbffff998
0xbffff800:     0xbffff9b6      0xbffff9c9      0xbffff9d3      0xbffffe14



最終更新 2010/08/19 18:03:26 - north
(2010/08/18 02:48:11 作成)


検索

アクセス数
3702489
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。