main函數的入口函數

操做系統裝載程序以後,首先運行的代碼並非main的第一行,而是某些別的代碼,這些代碼負責準備好main函數執行所須要的環境,而且負責調用main函數, 運行這些代碼的函數稱爲入口函數或入口點(Entry Point),視平臺的不一樣而有不一樣的名字。程序的入口點其實是一個程序的初始化和結束部分,它每每是運行庫的一部分。數組

一個典型的程序運行步驟

a. 操做系統在建立進程後,把控制權交到了程序的入口,這個入口每每是運行庫中的某個入口函數。
b. 入口函數對運行庫和程序運行環境進行初始化,包括堆、I/O、線程、全局變量構造,等等。
c. 入口函數在完成初始化以後,調用main函數,正式開始執行程序主體部分。
d. main函數執行完畢之後,返回到入口函數,入口函數進行清理工做,包括全局變量析構、堆銷燬、關閉I/O等,而後進行系統調用結束進程。數據結構

main函數入口點

MSVC的CRT默認的入口函數名爲 mainCRTStartup函數

  1. VC裏面預約義的一些全局變量,其中_osver和_winver表示操做系統的版本,_winmajor是主版本號等。經過調用GetVersionExA(這是一個Windows API)來得到當前的操做系統版本信息
  2. 一開始進行內存分配的不是malloc而是_alloca,此時尚未初始化堆,由於在程序的一開始堆尚未被初始化,而alloca是惟一能夠不使用堆的動態分配機制。alloca能夠在棧上分配任意大小的空間(只要棧的大小容許),而且在函數返回的時候會自動釋放,就好像局部變量同樣。
  3. 因爲沒有初始化堆,因此不少事情無法作,第一步把堆先初始化了:
if ( !_heap_init(0) )
    {
        fast_error_exit(_RT_HEAPINIT);
    }

- 這裏使用_heap_init函數對堆(heap)進行了初始化,若是堆初始化失敗,那
  麼程序就直接退出了。
- 它僅僅調用了HeapCreate的API建立了一個系統堆,那麼MSVC的malloc其實
  也是調用這個API將堆管理過程交給系統
  1. 使用_ioinit函數初始化了I/O,接下來這段代碼調用了一系列函數進行各類初始化,包括:操作系統

    1. _setargv:初始化main函數的argv參數。
    2. _setenv:設置環境變量。
    3. _cinit:其餘的C庫設置。
    4. FILE結構體命令行

      struct _iobuf 
      {
        char *_ptr;
        int _cnt;
        char *_base;
        int _flag;
        int _file;
        int _charbuf;
        int _bufsiz;
        char *_tmpfname;
      };
      typedef struct _iobuf FILE;
      - 這個FILE結構中最重要的一個字段是_file,_file是一個整數,經過_file能夠訪問到內部文件句柄表中的某一項。在Windows中,用戶態使用句柄(Handle)來訪問內核文件對象,句柄自己是一個32位的數據類型,在有些場合使用int來儲存,有些場合使用指針來表示。
    5. 在MSVC的CRT中,已經打開的文件句柄的信息使用數據結構ioinfo來表示:線程

      typedef struct 
          {
          intptr_t osfhnd;
          char osfile;
          char pipech;
          } ioinfo;
          □ 在這個結構中,osfhnd字段即爲打開文件的句柄,這裏使用8字節整數類型intptr_t來存儲。另外osfile的意義爲文件的打開屬性。而pipech字段則爲用於管道的單字符緩衝,這裏能夠先忽略。
          □ 在crt/src/ioinit/c中有一個數組-------ioinfo *_pioinfo[64]; //等效於 ioinfo _pioinfo[64][32]
          □ 二維上可容納32個ioinfo結構,所以該表可容納64 * 32 = 2048 個句柄
          □ 而FILE中_file的值就是和上面的osfhnd直接關聯
              ® _file中第五位到第十位是一維座標
              ® _file中第零位到第四位是二維座標
          □ 應用程序能夠經過API GetStartupInfo來繼承打開的文件

      e. 整體步驟指針

      1. 初始化和OS版本有關的全局變量。
      2. 初始化堆。
      3. 初始化I/O。
      4. 獲取命令行參數和環境變量。
      5. 初始化C庫的一些數據。
      6. 調用main並記錄返回值。
      7. 檢查錯誤並將main的返回值返回。
相關文章
相關標籤/搜索