2. 環境變數

先前講過,exec系統調用執行新程序時會把命令行參數和環境變數表傳遞給main函數,它們在整個進程地址空間中的位置如下圖所示。

圖 30.2. 進程地址空間

進程地址空間

和命令行參數argv類似,環境變數表也是一組字元串,如下圖所示。

圖 30.3. 環境變數

環境變數

libc中定義的全局變數environ指向環境變數表,environ沒有包含在任何標頭檔中,所以在使用時要用extern聲明。例如:

例 30.1. 打印環境變數

#include <stdio.h>

int main(void)
{
	extern char **environ;
	int i;
	for(i=0; environ[i]!=NULL; i++)
		printf("%s\n", environ[i]);
	return 0;
}

執行結果為

$ ./a.out 
SSH_AGENT_PID=5717
SHELL=/bin/bash
DESKTOP_STARTUP_ID=
TERM=xterm
...

由於父進程在調用fork創建子進程時會把自己的環境變數表也複製給子進程,所以a.out打印的環境變數和Shell進程的環境變數是相同的。

按照慣例,環境變數字元串都是name=value這樣的形式,大多數name由大寫字母加下劃線組成,一般把name的部分叫做環境變數,value的部分則是環境變數的值。環境變數定義了進程的運行環境,一些比較重要的環境變數的含義如下:

PATH

執行檔的搜索路徑。ls命令也是一個程序,執行它不需要提供完整的路徑名/bin/ls,然而通常我們執行當前目錄下的程序a.out卻需要提供完整的路徑名./a.out,這是因為PATH環境變數的值裡麵包含了ls命令所在的目錄/bin,卻不包含a.out所在的目錄。PATH環境變數的值可以包含多個目錄,用:號隔開。在Shell中用echo命令可以查看這個環境變數的值:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
SHELL

當前Shell,它的值通常是/bin/bash

TERM

當前終端類型,在圖形界面終端下它的值通常是xterm,終端類型決定了一些程序的輸出顯示方式,比如圖形界面終端可以顯示漢字,而字元終端一般不行。

LANG

語言和locale,決定了字元編碼以及時間、貨幣等信息的顯示格式。

HOME

當前用戶主目錄的路徑,很多程序需要在主目錄下保存配置檔案,使得每個用戶在運行該程序時都有自己的一套配置。

environ指針可以查看所有環境變數字元串,但是不夠方便,如果給出name要在環境變數表中查找它對應的value,可以用getenv函數。

#include <stdlib.h>
char *getenv(const char *name);

getenv的返回值是指向value的指針,若未找到則為NULL

修改環境變數可以用以下函數

#include <stdlib.h>

int setenv(const char *name, const char *value, int rewrite);
void unsetenv(const char *name);

putenvsetenv函數若成功則返回為0,若出錯則返回非0。

setenv將環境變數name的值設置為value。如果已存在環境變數name,那麼

unsetenv刪除name的定義。即使name沒有定義也不返回錯誤。

例 30.2. 修改環境變數

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
	printf("PATH=%s\n", getenv("PATH"));
	setenv("PATH", "hello", 1);
	printf("PATH=%s\n", getenv("PATH"));
	return 0;
}

$ ./a.out 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
PATH=hello
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

可以看出,Shell進程的環境變數PATH傳給了a.out,然後a.out修改了PATH的值,在a.out中能打印出修改後的值,但在Shell進程中PATH的值沒變。父進程在創建子進程時會複製一份環境變數給子進程,但此後二者的環境變數互不影響。