無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

コマンド引数と環境変数


環境変数は子プロセスへ引き継がれていく。すなわち各プロセス間で環境変を管理している。シェルからプロセスを起動すると、最終的にコマンド引数と環境変数を引数に取る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                      <- _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

argv[0]のアドレス0xbffff7d0+4にセットされている0xbffff8fc以降をダンプしてみると、上のアドレスに従ってコマンド変数と環境変数が続いている。
(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                      <- mainコール時のスタック内容
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/21 18:02:35 - north
(2010/08/18 02:48:11 作成)