【APUE】進程環境

本文章介紹進程的環境

1.main函數

    c程序總是從main函數開始執行的,其原型是
        int main(int argc, char **argv);
        //argc是命令行參數的個數
        //argv是指向參數的各個指針所構成的數組

2.進程終止

    有8種方式可以讓進程終止,其中前5種爲正常終止
    1.從main返回
    2.調用exit
    3.調用_exit或_Exit
    4.最後一個線程從其啓動例程返回
    5.最後一個線程調用pthread_exit
    6.調用abort
    7.接到一個信號並終止
    8.最後一個線程對取消請求做出響應

3.exit函數

    #include <stdlib.h>
    void exit(int status);
    void _Exit(int status);
    #include <unistd.h>
    void _exit(int status);
    //_exit和_Exit立即進入內核,exit則進行一些清理處理在進入內核
    由於歷史原因,exit函數總是要執行一個標準I/O庫的清理關閉操作fclose(),這將造成所有的緩衝區數據都被沖洗
    unix shell:#echo $? 可以顯示程序的返回值

4.atexit函數

    按照ISO C規定,一個進程可以登記多達32個函數,這些函數將由exit自動調用。
    我們稱這些函數爲終止處理函數,用下面的函數來登記這些函數:
    #include <stdlib.h>
    int atexit(void (*func)(void));
    //成功返回0,出錯返回非零值
    在程序即將結束的時候,調用登記過的函數,但是函數的執行順序和登記的順序是相反的
    根據ISO C和POSIX.2,exit函數首先調用各個終止處理函數,然後按需多次調用fclose函數,關閉所有打開的流。
    POSIX.1擴展了ISO C的標準,它指定如若程序調用exec函數族的任一函數,則將清除所有已安裝的終止處理函數。

5.命令行參數

    當執行一個程序的時候,調用exec的進程可將命令行參數傳遞給新程序。
    程序如下:

   
  1. #include <stdio.h>
  2.     #include <stdlib.h>
  3.     int main(int argc, char **argv)
  4.     {
  5.         int i;
  6.         for (i = 0; i < argc; i++) {
  7.             printf("argv[%d] = %s.\n", i, argv[i]);
  8.         }
  9.         exit(EXIT_SUCCESS);
  10.     }


6.環境表

    每個程序都會接受一張環境表,這個表和參數表一樣是一個字符指針數組,每個指針包含以NULL介紹給有的c字符串的地址
    在程序中聲明
        extern char **environ;
    在程序中輸出環境表
        for (i = 0; environ[i] != NULL; i++) {
            printf("environ[%d]: %s.\n", i, environ[i]);
        }
    環境表的每個字段的格式都是name=value

7.c語言的存儲空間佈局

    從歷史上將c語言一直由以下幾部分組成
    正文段:這是由CPU執行的機器指令部分。正文段是共享的,在存儲器中只有一個副本。另外正文段通常是隻讀的
    初始化數據段: 通常將此段稱爲數據段,它包含了程序中需明確的賦初值的變量。如:
        c語言中:
            int i = 0;
        此變量存在初始化數據段中
    非初始化數據段:通常將此段稱爲bss段。在程序開始執行之前,內核將此段中的數據初始化爲0或空指針。
    棧:自動變量以及每次函數調用時所需保存的信息都存放在此段中。每次調用函數時,其返回地址以及調用者的環
    境信息都存放到棧中。然後,最近被調用的函數在棧上爲其自動和臨時變量分配存儲空間。通過這種方式使用棧,
    可以遞歸調用c函數。遞歸函數每次調用自身時,就使用一個新的棧幀,因此一個函數調用實例中的環境變量不會
    影響到另一個函數調用實例中的變量。
    堆:通常在堆中進行動態存儲分配。堆位於非初始化數據段和棧之間。
    size命令則報告正文段,數據段和bss段的長度

8.存儲器分配

    ISO C說明了三種用於存儲器空間分配的函數
    #include <stdlib.h>
    void *malloc(size_t size);
    //分配指定字節數的存儲區。此存儲區中的初始值不確定。
    void *calloc(size_t nobj, size_t size);
    //在內存的動態存儲區中分配nobj個長度爲size的連續空間,存儲區中初始值均爲0。
    void *realloc(void *ptr, size_t newsize);
    //將ptr所指向的存儲區重新分配,當增加長度的時候新增的存取區中的初始值不確定。
    //這三個函數若成功返回非空指針,失敗返回NULL
    void free(void *ptr);
    //釋放存儲區空間

9.setjmp和longjmp

    在c語言中,goto語句是不能跨越函數的,最穩妥安全的跨越函數跳轉的函數是setjmp和longjmp
    #include <setjmp.h>
    int setjmp(jmp_buf env);
    //若直接調用返回0,若從longjmp調用返回非0值
    void longjmp(jmp_buf env, int val);
    //setjmp設置返回的位置,longjmp中的val是跳轉後的返回值

閱讀(186) | 評論(0) | 轉發(0) |
給主人留下些什麼吧!~~
評論熱議
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章