1. 程式人生 > >linux動態庫的初始化和清理

linux動態庫的初始化和清理

   a. Windows 中有 DllMain 入口函式, 而 Linux 中則沒有。

   b. Linux 中有特殊函式 _init 和 _fini, 主要是分別用來初始化動態庫和關閉的時候
      做一些必要的處理, 我們可以把自己認為需要的程式碼放到這兩個函式裡面, 它們分別
      在動態庫被載入和釋放的時候被執行。具體說, 如果一個動態庫裡面有一個名字為
      "_init" 的函式輸出, 那麼在第一次通過 dlopen() 函式開啟這個動態庫, 或者只是
      簡單的作為共享動態庫被開啟的時候, _init 函式被自動呼叫執行。與之相對應的就
      是 _fini 函式, 當一個程式呼叫 dlclose() 去釋放對這個動態

庫的引用的時候, 如
      果該動態庫的被引用計數器為 0 了, 或者這個動態庫是作為一般的共享動態庫被使
      用而使用它的程式正常退出的時候, _fini就會被呼叫執行。

      C語言定義它們的原型如下:
      void _init(void);
      void _fini(void);

      當使用你自己的 _init 和 _fini 函式時, 會出現命名衝突, 就會得到一個
      "multiple-definition" 的錯誤, 編譯器提示已經存在這個名字, 可以通過幾種方式
      來解決:
         1). 自定義 init 函式名字, 比如 myinit 用 -Wl, 選項給 ld 傳遞此名字:
         gcc ... -Wl,-init=myinit

         2). 當 GCC 編譯源程式時, 可以使用選項 -nostartfiles 來使共享庫不與系統
             啟動檔案一起編譯
         gcc ... -nostartfiles

         3). 使用上面的函式或 GCC 的 -nostartfiles 選項並不是很好的習慣, 因為這
             可能會產生一些意外的結果。相反, 庫應該使用
             __attribute__((constructor)) 和 __attribute__((destructor)) 函式屬
             性來輸出它的建構函式和解構函式。如下所示:

             void __attribute__((constructor)) x_init(void);
             void __attribute__((destructor))  x_fini(void);

             建構函式會在dlopen()返回前或庫被裝載時呼叫;
             解構函式會在這樣幾種情況下被呼叫: dlclose() 返回前, 或 main() 返回
             後, 或裝載庫過程中 exit() 被呼叫時。

   c. Linux 中的初始化和釋放函式不建議使用。