exportされた環境変数
Rev.1を表示中。最新版はこちら。
[コマンド引数と環境変数]でシェルで環境変数としてexportはシェルが管理していて、シェルプロセスとしてこの変数が環境変数に設定されるわけでない。と言いました。このことを検証してみます。/proc/pid/environからそのプロセスの環境変数を取得することができます。/proc/pid/environがreadされると、struct file_operations proc_environ_operationsで定義される、redaコールバック関数environ_read関数が呼ばれることになります。
ここでは指定されるinodeからプロセスIDを、そしてそのtask_struct構造体を取得します。task_structにはmm_struct構造体が紐づいています。
さきに環境変数はユーザのスタックエリアを拡張し、そこに設定されていることを確認しました。(正確には環境変分スタックエリアを拡張する。)実はこのときそのスタック内に設定した環境変数の設定エリアを、mm_struct->env_startとmm_struct->env_endに設定しています。
environ_read関数ではこのメンバーからそのプロセスの環境変数を取得しています。カーネルとしてはそれがユーザのスタックエリアなんかどうでもいい訳です。そしてこれがまさにプロセスとして認識している環境変数といえそうです。
exportというコマンドは環境変数を設定するというもので、exportすることでシェルプロセスの環境変数を格納しているスタックエリアに追加するものと思っていました。
[root@KURO-BOXHG ~]# export TEST=111 [root@KURO-BOXHG ~]# printenv HOSTNAME=KURO-BOXHG TERM=xterm SHELL=/bin/bash : TEST=111 SHLVL=1 :しかし/proc下のenvironをみてみると、TEST=111がありません。環境変数は/proc下のenvironで表示されるもの以外ありません。
[root@KURO-BOXHG ~]# cat /proc/20120/environ USER=rootLOGNAME=rootHOME=/rootPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/us r/binMAIL=/var/mail/rootSHELL=/bin/bashSSH_CLIENT=192.168.200.28 14706 22SSH_CONNECTION=192.168.200.28 14706 192.168.200.150 22SSH_TTY=/dev/pts/0TERM=xterm
実はexportはシェルコマンドで、printenvは外部コマンドです。推測ですが、printenvが表示している環境変数は自分自身の環境変数を表示しているものと思われます。シェルとしてはexecで、カーネル下が管理しているシェルプロセスとしての環境変数とexportで設定されたシェルとしてのユーザプログラムとして管理している環境変数をマージしてexecをコールしていると考えられます。
ただ言えることは、シェルから子プロセスを起動した場合、子プロセスのスタックエリアにはexportされた環境変数も設定されているということは間違いないようです。(でないと、そこからまた子プロセスを起動すると環境変数が引き継がれなくなりますから。)