入口函數和程序初始化

能夠參考《程序員的自我修養》裝載、連接和庫linux

linux加載程序的過程簡單點說就是linux創建一個進程,而後讀取可執行文件頭,而且創建虛擬空間與可執行文件的映射關係,最後把cpu的指令寄存器設置成可執行文件的入口地址,啓動執行。而後依次執行代碼段的指令。

 

 

一、程序並非從main函數開始的。好比下面的程序:程序員

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

int a = 3;

int main(int argc, char *argv[])
{
	int *p = (int *)malloc(sizeof(int));
	scanf("%d", p);
	printf("%d", a + *p);
	free(p);
}


#include <string>
using namespace std;
string v;
double foo()
{
	return 1.0;
}

double g = foo();
int main() {}

  

從代碼中咱們能夠看到,在程序剛剛執行到main的時候,全局變量的初始化過程已經結束了(a的值已經肯定),main函數的兩個參數(argc和argv)也被正確傳了進來。此外,在你不知道的時候,堆和棧的初始化悄悄地完成了,一些系統I/O也被初始化了,所以能夠放心地使用printf和malloc。函數

第二個C++程序,對象v的構造函數,以及用於初始化全局變量g的函數foo都會在main以前調用。spa

 

操做系統裝載程序以後,首先運行的代碼並非main的第一行,而是某些別的代碼,這些代碼負責準備好main函數執行所須要的環境,而且負責調用main函數,這時候你才能夠在main函數裏放心大膽地寫各類代碼:申請內存、使用系統調用、觸發異常、訪問I/O。在main返回以後,它會記錄main函數的返回值,調用atexit註冊的函數,而後結束進程。操作系統

運行這些代碼的函數成爲入口函數或入口點,視平臺的不一樣而有不一樣的名字。程序的入口點其實是一個程序的初始化和結束部分,它每每是運行庫的一部分。一個典型的程序運行步驟大體以下:線程

(1)操做系統在建立進程後,把控制權交到了程序的入口,這個入口每每是運行庫中的某個入口函數。對象

(2)入口函數對運行庫和程序運行環境進行初始化,包括堆、I/O、線程、全局變量構造,等等blog

(3)入口函數在完成初始化以後,調用main函數,正式開始執行程序主題部分。進程

(4)main函數執行完畢之後,返回到入口函數,入口函數進行清理工做,包括全局變量析構、堆銷燬、關閉I/O等,而後進行系統調用結束進程。內存

相關文章
相關標籤/搜索