1. 程式人生 > >第七章 高級環境

第七章 高級環境

CP c編譯器 全局變量 register return AR 打開 close 編程

第七章 高級環境 7.2 main函數 C程序總是從main函數開始執行的。main函數的原型是: int main(int argc, char *argv[]); 其中,argc是命令行參數的數目,argv是指向參數的各個指針所構成的數組。 當內核執行C程序的時候(使用一個exec函數),在調用main前先調用一個特殊的啟動例程。可執行程序文件將此啟動例程指定為程序的起始地址-- 這是由連接編輯器設置的,而連接編輯器則是由C編譯器調用的。啟動例程從內核取得命令行參數和環境變量值,然後為按上述方式調用main函數做好安排。 7.3進程終止 有8種方式使進程終止。其中5種為正常終止,依次是:
  • 從main函數返回
  • 調用exit
  • 調用_exit或_Exit
  • 最後一個線程從期啟動例程返回
  • 從最後一個線程調用pthread_exit
異常終止有3種,依次為:
  • 調用abort
  • 接到一個信號
  • 最後一個線程對取消請求做出響應
7.3.1 退出函數 3個函數用於正常終止一個程序:_exit和_Exit立即進入內核,exit則先執行一些清理處理,然後返回內核。 #include <stdlib.h> void exit(int status); void _Exit(int status); #include <unistd.h> void _exit(int status); //exit函數總是執行一個標準I/O庫的清理關閉操作:對所有打開流調用fclose函數。 3個退出函數都帶一個整型參數,稱為終止狀態。如果 調用這些函數時不帶參數 或 main執行了一個無返回值的return語句 或 main沒有聲明返回類型為整型 則該進程的終止狀態為未定義的。但是,若main返回類型是整型,並且main執行到最後一條語句時返回,則該進程的終止狀態是0; main函數返回一個整型值與用該值調用exit是等價的。於是在main函數中exit(0)等價於return(0); 7.3.2 atexit 按照ISO C的規定,一個進程可以登記多至32個函數,這些函數將由exit自動調用。我們稱這些函數為終止處理程序,並調用atexit函數來登記這些函數。 #include<stdlib.h> int atexit(void (*func)(void)); 也就是說通過atexit函數登記若幹函數,在程序退出時會自動調用被登記的函數。 技術分享圖片
技術分享圖片 說明使用atexit函數。 #include <stdlib.h> #include <stdio.h> static void my_exit1(void); static void my_exit2(void); int main(void) { if (atexit(my_exit2) != 0) { printf("can‘t register my_exit2\n"); } if (atexit(my_exit1) != 0) { printf("can‘t register my_exit1\n"); } if (atexit(my_exit1) != 0) { printf("can‘t register my_exit1\n"); } printf("main id done\n"); return 0; } static void my_exit1(void) { printf("first exit handler\n"); } static void my_exit2(void) { printf("second exit handler\n"); } 技術分享圖片
技術分享圖片 7.4命令行參數 當執行一個程序的時候,調用exec的進程可以將命令行參數傳遞給該新函數。 #include<stdio.h> int main(int args, char *argv[]) { int i; for (i = 0; i<args; i++) { printf("argv[%d]:%s\n", i, argv[i]); } return 0; } 技術分享圖片 技術分享圖片 7.5環境表 每個程序都接收到一張環境表。與參數表一樣,環境表也是一個字符指針數組。其中每個指針包含一個以null結尾的C字符串地址。全局變量 environ則包含了該指針數組的地址:extern char **environ; 7.6 C程序的存儲空間布局 C程序一直由下列部分構成:
  • 正文段。這是由CPU執行的機器指令部分。通常,正文段是可共享的,所以即使是頻繁的執行的程序在存儲器中也只需有一個副本。此外正文段常常是只讀的,以防止程序由於意外而修改其指令。
  • 初始化數據段。通常將此段稱為數據段,它包含了程序中需明確地賦初值的變量。例如,在C程序中任何函數之外的聲明:int maxcoubnt =99; 使此變量以其初值存放在初始化數據段中。
  • 未初始化數據段。通常將此段稱為bss段。這一名稱來源於早期匯編程序一個操作符,意思是“由符號開始的塊”,在程序開始執行前,內核將此段中的數據初始化為0或空指針。函數外聲明:long sum[10];
  • 棧。自動變量以及每次函數調用時所需保存的信息都存放在此段中。每次函數調用時,其返回地址以及調用者的環境信息(如某些機器寄存器的值)都存放在棧中。然後,最近被調用的函數在棧上為其自動和臨時變量分配存儲空間。
  • 堆。通常在堆中進行動態存儲分配。由於歷史形成的慣例,堆位於未初始化數據段和棧之間。
技術分享圖片 技術分享圖片

第七章 高級環境