Linux操作系統-進程和信號(1)

Linux操作系統—進程和信號(1)

分類:Linux操作系統

Linux進程環境

程序的入口

  C程序總是從main函數開始執行。來好好了解一下main函數吧(C語言課上學的簡直連皮毛都達不到)main函數的原型如下:

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

  其中,argc是命令行參數的數目,argv是指向命令參數的各指針所構成的數組。下面是一個例子,作用是將命令行傳遞給程序的參數打印出來。

#include <stdio.h>

int main(int argc, char *argv[])
{
    int i;

    for (i = 0; i < argc; i++)
        printf("argv[%d] : %s\n", i, argv[i]);

    return 0;
}

  編譯並運行

biantiao@lazybone1994-ThinkPad-E430:~/桌面$ gcc -o main main.c
biantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./main a.txt b.txt
argv[0] : ./main
argv[1] : a.txt
argv[2] : b.txt
biantiao@lazybone1994-ThinkPad-E430:~/桌面$

進程的終止

  正常終止的情況
1. 從main返回
2. 調用exit
3. 調用_exit

  異常終止的情況
1. 被一個系統信號終止
2. 調用abort,它產生SIGABRT信號,是一種異常終止的特例

exit和_exit的區別

  eixt和_exit都用於正常終止一個程序,它們的區別是:_exit立即進入內核,exit則先執行一些清除處理(包括調用執行各終止處理程序,關閉所有標準I/O流等),然後進入內核。exit屬於標準函數庫,而exit是底層系統調用,它們的原型分別如下:

#include <stdlib.h>
void exit(int status);
#include <unistd.h>
void _exit(int status);

  exit函數會執行一個標準I/O庫的清除關閉操作,即對所有打開的流調用fclose函數.

atexit函數

  上面說到了exit函數會執行一個標準I/O庫的清除關閉操作,那這是怎麼實現的呢?答案就是通過atexit函數實現。
  ANSI C規定,一個進程可以登記多至32個由exit自動調用的函數,這些函數被稱爲終止處理程序(exit handler)。登記終止處理程序要使用atexit函數,它的函數原型如下:

#include <stdlib.h>
int atexit(void (*function)(void));

  atexit的參數是一個函數地址,atexit函數成功時返回0,失敗時返回非0值。要注意的是exit函數以登記這些函數的相反順序調用它們。同一函數如果多次登記,則也將被調用多次。下面是一個使用atexit函數的例子

#include <stdio.h>

static void my_exit1(void);
static void my_exit2(void);

int main(int argc, char *argv[])
{
    if (atexit(my_exit2) != 0){            /* 登記my_exit2 */
        puts("Register my_exit2 failed.");
        return -1;
    }

    if (atexit(my_exit1) != 0){            /* 登記my_exit1 */
        puts("Register my_exit1 failed.");
        return -1;
    }

    puts("Main is done.");
    return 0;
}

static void my_exit1(void)
{
    puts("First exit handler.");
}

static void my_exit2(void)
{
    puts("Second exit handler.");
}

  編譯並運行,要注意的是exit以與登記這些函數的相反順序調用它們

biantiao@lazybone1994-ThinkPad-E430:~/桌面$ gcc -o atexit atexit.c
biantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./atexit
Main is done.
First exit handler.
Second exit handler.
biantiao@lazybone1994-ThinkPad-E430:~/桌面$

環境表

  每個進程在啓動時都能收到一張環境表。與命令行的參數一樣,環境表也是一個字符指針數組,其中每個指針包含一個以null結束的字符串地址。全局變量environ記錄了該指針數組的地址。
extern char **environ;
  全局變量environ稱爲環境指針,其所指向的數組稱爲環境表,數組中的每個指針指向的字符串稱爲環境字符串。環境字符串具有約定的形式如”name=value”的格式。

C程序的存儲空間佈局

  C程序的存儲空間一般由一下幾個部分組成
- 正文段:由CPU執行的機器指令構成.通常,正文段共享的,所以同時啓動一個程序的多個進程,在內存中只有一個正文段的副本.另外,正文段常常是隻讀的,這可以防止程序由於意外事故而修改自身的指令.
- 初始化數據段:由程序中已賦值的靜態變量構成.
- 非初始化數據段:常稱爲bss段,在程序開始執行之前,內核將此段初始化爲0.
- 棧:自動變量以及每次函數調用時所需保存的場景信息存放在此段中.另外函數調用時也使用棧來傳遞參數,被調用的函數則在棧上爲其自動變量和臨時變量分配存儲空間
- 堆:通常在堆中進行動態分配。堆位於非初始化數據段頂和棧底之間

  可以使用size命令查看一個可執行程序的正文段,數據段和bss段的字節數

靜態庫和共享庫

  什麼是庫?庫就是可複用的二進制可執行代碼的有序集合
  Linux下有兩種類型的庫,分別是靜態庫和共享庫。兩種的一個重要區別在於其中的代碼被載入的時刻不同。
- 使用靜態庫的程序,在編譯鏈接過程即載入靜態庫的代碼並將靜態庫的代碼置入編譯出的可執行程序。
- 使用共享庫的程序,在編譯鏈接過程中僅對共享庫作簡單引用,在程序運行時纔將共享庫的代碼載入內存。

  在Linux下,庫文件一般放在/usr/lib和/lib下。靜態庫的名字一般爲libxxxx.a,其中xxxx是該庫的名字。動態庫的名字一般爲libxxxx.so.major.minor,其中xxxx是該庫的名稱,major是主版本號,minor是次版本號。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章