從零開始UNIX環(huán)境高級編程(7):進(jìn)程環(huán)境

0. 引言

在學(xué)習(xí)進(jìn)程控制前拯勉,先了解進(jìn)程運(yùn)行的環(huán)境蚁滋,如:main函數(shù)是如何被調(diào)用的;命令行參數(shù)是如何傳遞給新程序的焦匈;程序在內(nèi)存空間中是什么樣的結(jié)構(gòu)血公;進(jìn)程的終止方式等。

進(jìn)程環(huán)境

1. main函數(shù)

1.1 程序執(zhí)行的入口函數(shù)

雖然C程序總是從main函數(shù)開始執(zhí)行缓熟,但是內(nèi)核使用exec函數(shù)執(zhí)行C程序時累魔,在調(diào)用main前會先調(diào)用一個啟動例程,這個啟動例程就是_start够滑。以下面這段代碼為例垦写,通過gcc test.c -o test編譯生成可執(zhí)行文件test

/*test.c*/
int main()
{
    return 0;
}

使用objdump對test進(jìn)行分析彰触,得到反匯編結(jié)果如下梯澜,可以看出main函數(shù)地址為0x4004b4,在_start有去調(diào)用到mov $0x4004b4,%rdi渴析。這個示例只是為了證明main函數(shù)是由啟動例程_start調(diào)用的,此處不過多的去探究反匯編得到的這些符號的含義吮龄,有興趣的同學(xué)可以參考 程序員的自我修養(yǎng):鏈接俭茧、裝載與庫第11章的第1節(jié) 入口函數(shù)和程序初始化

ckt@ubuntu:~/work/unix/code/chapter7$ objdump -S -d signal.o
... ...

00000000004003d0 <_start>:
  4003d0:   31 ed                   xor    %ebp,%ebp
  4003d2:   49 89 d1                mov    %rdx,%r9
  4003d5:   5e                      pop    %rsi
  4003d6:   48 89 e2                mov    %rsp,%rdx
  4003d9:   48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
  4003dd:   50                      push   %rax
  4003de:   54                      push   %rsp
  4003df:   49 c7 c0 50 05 40 00    mov    $0x400550,%r8
  4003e6:   48 c7 c1 c0 04 40 00    mov    $0x4004c0,%rcx
  4003ed:   48 c7 c7 b4 04 40 00    mov    $0x4004b4,%rdi
  4003f4:   e8 c7 ff ff ff          callq  4003c0 <__libc_start_main@plt>
  4003f9:   f4                      hlt    
  4003fa:   90                      nop
  4003fb:   90                      nop
 
  ... ...

  00000000004004b4 <main>:
  4004b4:   55                      push   %rbp
  4004b5:   48 89 e5                mov    %rsp,%rbp
  4004b8:   b8 00 00 00 00          mov    $0x0,%eax
  4004bd:   5d                      pop    %rbp
  4004be:   c3                      retq   
  4004bf:   90                      nop
... ...

1.2 命令行參數(shù)

接著來看main函數(shù)的參數(shù)漓帚,main函數(shù)原型如下

int main(int argc, char const *argv[])

通過命令行運(yùn)行一個C程序時母债,我們可以通過命令行傳入?yún)?shù)。main函數(shù)中的參數(shù)argc表示參數(shù)個數(shù)尝抖,argv中存放的是參數(shù)值毡们。

  • 示例
    使用如下代碼打印出從命令行傳入的參數(shù)
#include "apue.h"

int main(int argc, char const *argv[])
{
    int i = 0;
    for (i = 0; i < argc; i++)
        printf("%s\n", argv[i]);
    return 0;
}
  • 運(yùn)行結(jié)果
ckt@ubuntu:~/work/unix/code/chapter7$ cc get_arg.c -o get_arg
ckt@ubuntu:~/work/unix/code/chapter7$ ./get_arg
./get_arg
ckt@ubuntu:~/work/unix/code/chapter7$ ./get_arg test1 test2 test3 
./get_arg
test1
test2
test3

1.3 環(huán)境表

大多數(shù)UNIX系統(tǒng)支持main函數(shù)帶3個參數(shù),其中第3個參數(shù)envp就是環(huán)境變量表的地址昧辽,和argv一樣衙熔,evnp也是一個數(shù)組

int main(int argc, char const *argv[], char *envp[])
envp示意圖
  • 示例
    打印出當(dāng)前程序的環(huán)境變量表
#include "apue.h"

void printinfo(char * info)
{
    int i = 0;
    while (info[i] != '\0')
    {
        printf("%c", info[i]);
        i++;
    }
    printf("  ");
}

int main(int argc, char const *argv[], char *envp[])
{
    while (*envp != NULL)
    {
        printinfo(*envp);
        envp++;
    }

    printf("\n");

    return 0;
}
  • 運(yùn)行結(jié)果
    由于打印的環(huán)境變量值太多,省略部分打印結(jié)果搅荞。
ckt@ubuntu:~/work/unix/code/chapter7$ cc get_environ.c -o get_environ
ckt@ubuntu:~/work/unix/code/chapter7$ ./get_environ
SSH_AGENT_PID=2030  SHELL=/bin/bash  OLDPWD=/home/ckt/work/unix/code/chapter10  
LANG=en_US.UTF-8 HOME=/home/ckt _=./get_environ  

2. C程序的存儲空間布局

C程序通常由5個部分組成:

  • 正文段(.text):存放CPU的機(jī)器指令
  • 初始化數(shù)據(jù)段(.data):存放全局靜態(tài)變量和局部靜態(tài)變量
  • 未初始化數(shù)據(jù)段(.bss):存未初始化的全局變量和局部靜態(tài)變量
  • 棧(stack):存放局部變量和函數(shù)調(diào)用時所需保存的信息
  • 堆(heap):動態(tài)分配的變量
典型的存儲空間安排

我們同樣可以通過objdump去分析各個段红氯,如果想要了解更多細(xì)節(jié),請參考使用readelf和objdump解析目標(biāo)文件

程序與目標(biāo)文件對應(yīng)關(guān)系

3. 共享庫

共享庫使得可執(zhí)行文件中不再需要包含公用的庫函數(shù)咕痛,只需要在進(jìn)程可引用的儲存區(qū)保存這個庫例程的一個副本痢甘。共享庫有以下兩個優(yōu)點(diǎn):
1. 減少了可執(zhí)行文件的長度
2. 可以用庫函數(shù)的新版本代替老版本,而無需對使用該庫的程序重新連接編輯

  • 示例

先用無共享方式創(chuàng)建可執(zhí)行文件a.out茉贡,并使用size命令查看正文段和數(shù)據(jù)段的長度

ckt@ubuntu:~/work/unix/code/chapter7$ gcc -static test.c 
ckt@ubuntu:~/work/unix/code/chapter7$ ls -l a.out 
-rwxrwxr-x 1 ckt ckt 883375 Apr 24 04:30 a.out
ckt@ubuntu:~/work/unix/code/chapter7$ size a.out 
   text    data     bss     dec     hex filename
 790568    6128   11272  807968   c5420 a.out

再使用共享庫編譯此程序塞栅,得到的可執(zhí)行文件的正文和數(shù)據(jù)段長度明顯減小

ckt@ubuntu:~/work/unix/code/chapter7$ gcc test.c
ckt@ubuntu:~/work/unix/code/chapter7$ ls -l a.out 
-rwxrwxr-x 1 ckt ckt 8326 Apr 24 04:30 a.out
ckt@ubuntu:~/work/unix/code/chapter7$ size a.out 
   text    data     bss     dec     hex filename
   1076     496      16    1588     634 a.out

4. 動態(tài)存儲空間分配

存儲空間分配

5. 環(huán)境變量

當(dāng)我們登錄Linux之后,使用shell來跟系統(tǒng)進(jìn)行通信腔丧,在進(jìn)入shell之前放椰,系統(tǒng)需要一些變量來提供它的數(shù)據(jù)訪問(如是否顯示彩色作烟、當(dāng)前路徑和主文件夾的路徑等),這些變量就是環(huán)境變量庄敛。為了區(qū)別于自定義變量俗壹,環(huán)境變量通常用大寫字符表示。

5.1 終端中獲取和設(shè)置環(huán)境變量

使用env命令可以列出當(dāng)前shell環(huán)境下的所有環(huán)境變量

ckt@ubuntu:~/work/unix/code/chapter7$ env
SSH_AGENT_PID=2030
GPG_AGENT_INFO=/tmp/keyring-NWSXuo/gpg:0:1
TERM=xterm
SHELL=/bin/bash
XDG_SESSION_COOKIE=b2968a33ddb5564574638ff00000000f-1492995827.229855-1165390831
WINDOWID=71303173
OLDPWD=/home/ckt/work/unix/code/chapter10
GNOME_KEYRING_CONTROL=/tmp/keyring-NWSXuo
USER=ckt
... ...

使用echo $環(huán)境變量名命令可以查看單個環(huán)境變量藻烤,例如绷雏,當(dāng)前路徑保存在環(huán)境變量PWD中

ckt@ubuntu:~/work/unix/code/chapter7$ echo $PWD
/home/ckt/work/unix/code/chapter7

使用PATH=$PATH:/home/ckt/work/unix/給PTAH變量追加路徑/home/ckt/work/unix/

ckt@ubuntu:~/work/unix/code/chapter7$ echo $PATH
/home/ckt/work/msm8939-la-2-1/LINUX/android/out/host/linux-x86/bin:/home/ckt/work/adt-bundle-linux-x86_64-20140702/sdk/platform-tools:/home/ckt/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
ckt@ubuntu:~/work/unix/code/chapter7$ PATH=$PATH:/home/ckt/work/unix/
ckt@ubuntu:~/work/unix/code/chapter7$ echo $PATH
/home/ckt/work/msm8939-la-2-1/LINUX/android/out/host/linux-x86/bin:/home/ckt/work/adt-bundle-linux-x86_64-20140702/sdk/platform-tools:/home/ckt/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/ckt/work/unix/
ckt@ubuntu:~/work/unix/code/chapter7$ 

5.2 使用getenv獲得環(huán)境變量

  • 示例
#include "apue.h"

int main(int argc, char const *argv[])
{
    char * home = NULL;
    char * shell = NULL;
    char * path = NULL;

    if ((home = getenv("HOME")) != NULL)
        printf("%s\n", home);

    if ((shell = getenv("SHELL")) != NULL)
        printf("%s\n", shell);

    if ((path = getenv("PATH")) != NULL)
        printf("%s\n", path);

    return 0;
}
  • 運(yùn)行結(jié)果
ckt@ubuntu:~/work/unix/code/chapter7$ cc getenv_test.c -o getenv_test
ckt@ubuntu:~/work/unix/code/chapter7$ ./getenv_test
/home/ckt
/bin/bash
/home/ckt/work/msm8939-la-2-1/LINUX/android/out/host/linux-x86/bin:/home/ckt/work/adt-bundle-linux-x86_64-20140702/sdk/platform-tools:/home/ckt/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

5.3 通過函數(shù)設(shè)置環(huán)境變量

  • 示例
#include "apue.h"

void print_pwd(char * info)
{
    char * pwd = NULL;

    printf("%s : ", info);

    if ((pwd = getenv("PWD")) != NULL)
        printf("%s\n", pwd);
    else
        printf("pwd is NULL \n");

}

int main(int argc, char const *argv[])
{
    print_pwd("before setenv");

    if (setenv("PWD", "test", 1) < 0)
        err_sys("setenv error");

    print_pwd("after setenv");

    if (unsetenv("PWD") < 0)
        err_sys("unsetenv error");

    print_pwd("after unsetenv");

    return 0;
}
  • 運(yùn)行結(jié)果
ckt@ubuntu:~/work/unix/code/chapter7$ cc setenv_test.c -o setenv_test
ckt@ubuntu:~/work/unix/code/chapter7$ ./setenv_test
before setenv : /home/ckt/work/unix/code/chapter7
after setenv : test
after unsetenv : pwd is NULL 

6. 進(jìn)程終止

進(jìn)程終止

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涎显,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子兴猩,更是在濱河造成了極大的恐慌期吓,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倾芝,死亡現(xiàn)場離奇詭異讨勤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)晨另,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門潭千,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人借尿,你說我怎么就攤上這事刨晴。” “怎么了路翻?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵狈癞,是天一觀的道長。 經(jīng)常有香客問我茂契,道長蝶桶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任掉冶,我火速辦了婚禮莫瞬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘郭蕉。我一直安慰自己疼邀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布召锈。 她就那樣靜靜地躺著旁振,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拐袜,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天吉嚣,我揣著相機(jī)與錄音,去河邊找鬼蹬铺。 笑死尝哆,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的甜攀。 我是一名探鬼主播秋泄,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼规阀!你這毒婦竟也來了恒序?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤谁撼,失蹤者是張志新(化名)和其女友劉穎歧胁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厉碟,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喊巍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了箍鼓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玄糟。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖袄秩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逢并,我是刑警寧澤之剧,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站砍聊,受9級特大地震影響背稼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜玻蝌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一蟹肘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧俯树,春花似錦帘腹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春球化,著一層夾襖步出監(jiān)牢的瞬間秽晚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工筒愚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赴蝇,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓巢掺,卻偏偏與公主長得像句伶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子址遇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理熄阻,服務(wù)發(fā)現(xiàn),斷路器倔约,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • 一秃殉、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 7,779評論 0 27
  • 1. 進(jìn)程標(biāo)識 1.1 進(jìn)程ID 由于每個進(jìn)程ID都是唯一的,Unix使用進(jìn)程ID作為進(jìn)程的標(biāo)識浸剩。使用ps命令可以...
    傷口不該結(jié)疤閱讀 1,819評論 0 51
  • 心:今天開始钾军,我就要『簡書』上說話了,好像還有些小小激動绢要。萬一吏恭,簡友們都不喜歡,怎么辦重罪? 靈:不喜歡你就不說話了嗎...
    靜菥閱讀 237評論 0 1
  • 12306大量數(shù)據(jù)泄露 來源 今早烏云漏洞平臺突然爆出了一個駭人聽聞的消息:12306用戶資料疑似大量泄漏剿配,甚至有...
    Vaayne閱讀 870評論 1 3