
しばらく前に、単純なCプログラムのELFバイナリを探索するためにGDBを使用していました。printenv
端末で実行すると、印刷された環境変数がその端末で実行されているCプログラムバイナリのスタックの上部にも表示されることを確認しました。
Bashは実際にどのようにプログラムを実行し、同時にすべての環境変数を新しいプロセスのスタックに追加しますか?簡単に言えば、次のようなプログラムを実行すると、段階的に何が起こりますか?
./myprogram
答え1
Linuxプログラムはexecve
システムコールを介して実行されます。execve
次の署名があります。
int execve(const char *filename, char *const argv[], char *const envp[]);
最後のパラメータenvp
は、環境を文字列配列としてプロセスに渡すために使用され、各文字列はkey = value形式です。通常、呼び出しプロセスが環境を一部変更しない限り、同じ環境はあるプロセスから別のプロセスに渡されます。カーネルは、プログラム引数を渡すように、新しいプログラムがスタックの環境を受け取るように準備します。
ライブラリ関数execl
、execlp
およびexecv
はexecvp
パラメータを使用しませんenvp
(ただし、execle
関数execvpe
はパラメータを使用します)。これらの関数は、environ
呼び出しプロセスのグローバル変数から環境を取得します。これにより、関数を使用してexecle
他のプログラムを起動するプログラムは環境の配布を心配する必要はありませんが、ライブラリ関数は自動的に「背後に」これを実行します。
言及されているすべてのライブラリ関数は最終的にexecve
システムコールを呼び出し、パラメータに環境を渡しますenvp
。