熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

LINUX系統中動態鏈接庫的創建與使用

2013-11-13 15:52:05  來源: Oracle 

  大家都知道在WINDOWS系統中有很多的動態鏈接庫(以DLL為後綴的文件DLL即Dynamic Link Library)這種動態鏈接庫和靜態函數庫不同它裡面的函數並不是執行程序本身的一部分而是根據執行程序需要按需裝入同時其執行代碼可在多個執行程序間共享節省了空間提高了效率具備很高的靈活性得到越來越多程序員和用戶的青睐那麼在LINUX系統中有無這樣的函數庫呢?
  答案是肯定的LINUX的動態鏈接庫不僅有而且為數不少在/lib目錄下就有許多以so作後綴的文件這就是LINUX系統應用的動態鏈接庫只不過與WINDOWS叫法不同它叫so即Shared Object共享對象(在LINUX下靜態函數庫是以a作後綴的) XWINDOW作為LINUX下的標准圖形窗口界面它本身就采用了很多的動態鏈接庫(在/usr/XR/lib目錄下)以方便程序間的共享節省占用空間著名的APACHE網頁服務器也采用了動態鏈接庫以便擴充程序功能你只需將PHP動態鏈接庫拷到其共享目錄修改一下配置APACHE就可以支持PHP網頁了如果你願意可以自己編寫動態鏈接庫讓APACHE支持你自己定義的網頁格式這就是動態鏈接的好處
  LINUX下動態鏈接庫的創建
  在LINUX系統下創建動態鏈接庫是件再簡單不過的事情只要在編譯函數庫源程序時加上shared選項即可這樣所生成的執行程序即為動態鏈接庫從某種意義上來說動態鏈接庫也是一種執行程序按一般規則程序名應帶so後綴下面舉個例子說說
  我准備編寫兩個函數一個用於查詢當前日期getdate一個用於查詢當前時間gettime並將這兩個函數存於動態鏈接庫myso中為此需要做以下幾項工作
   編寫用戶接口文件datetimeh內容如下(每行前面的數字為行號)
  
   /* datetimeh : 縱橫軟件制作中心雨亦奇編寫 */
  
   #ifndef __DATETIME_H
  
   #define __DATETIME_H
  
   /* 日期結構 */
   typedef struct
   {
   int year;
   int mon;
   int day;
   }DATETYPE;
  
   /* 時間結構 */
   typedef struct
   {
   char hour;
   char min;
   char sec;
   }TIMETYPE;
  
   /* 函數原型說明 */
  
   #ifdef SHARED
   int (*getdate)(DATETYPE *d);
   #else
   int getdate(DATETYPE *d);
   #endif
  
   #ifdef SHARED
   int (*gettime)(TIMETYPE *t);
   #else
   int gettime(TIMETYPE *t);
   #endif
  
   #endif
  
  
  這個用戶接口文件中先定義了日期與時間結構接著定義一下函數的原型動態函數與靜態函數的原型說明不同的是動態函數應使用(*函數名)的形式以便引用其指針若要引用文件中的動態函數說明用戶應該定義一下SHARED宏這樣才能使用
   編寫getdatec源程序如下
  
   /* getdatec : 縱橫軟件制作中心雨亦奇編寫 */
  
   #include timeh
   #include datetimeh
  
   int getdate(DATETYPE *d)
   {
   long ti;
   struct tm *tm;
  
   time(&ti);
   tm=localtime(&ti);
   d>year=tm>tm_year+;
   d>mon=tm>tm_mon+;
   d>day=tm>tm_mday;
   }
  
  
  在getdate函數中先調用time取得以秒計的系統時間再用localtime函數轉換一下時間結構最後調整得到正確的日期
   編寫gettimec源程序如下
  
   /* gettimec : 縱橫軟件制作中心雨亦奇編寫 */
  
   #include timeh
   #include datetimeh
  
   int gettime(TIMETYPE *t)
   {
   long ti;
   struct tm *tm;
  
   time(&ti);
   tm=localtime(&ti);
   t>hour=tm>tm_hour;
   t>min=tm>tm_min;
   t>sec=tm>tm_sec;
   }
  
  
  gettime函數與getdate函數相仿先用time函數取得以秒計的系統時間再用localtime函數轉換一下時間結構最後返回當前的時間(不需調整)
   編寫維護文件makefilelib內容如下
  
   # makefilelib : 縱橫軟件制作中心雨亦奇編寫
  
   all : myso
  
   SRC = getdatec gettimec
  
   TGT = $(SRC:c=o)
  
   $(SRC) : datetimeh
   @touch $@
  
   %o : %c
   cc c $?
  
   # 動態函數庫(myso)生成
   myso : $(TGT)
   cc shared o $@ $(TGT)
  
  
  編寫維護文件的目的在於方便程序員維護程序尤其是維護比較大的工程項目一個素質良好的程序員應該學會熟練地編寫維護文件makefile定義了文件間的依賴關系後一旦源文件發生變化僅需make一下其目標文件維護代碼會自動執行從而自動更新目標文件減少了許多工作量注意: 每行維護代碼必須以TAB(跳格鍵)開始不是的話make時將出錯
  本維護文件第行是注釋行以#號開頭文件第行定義所有需要維護的函數庫行定義相關源程序文件行定義目標文件行說明所有源程序依賴於datetimeh頭文件並有相應維護代碼即touch一下更新一下源文件的時間行定義o文件依賴於相應的c文件並指定了維護代碼即用cc編譯一下行定義共享庫myso依賴的目標文件維護代碼中用shared編譯選項以生成動態鏈接庫myso
   運行make f makefilelib 命令
  make運行後動態鏈接庫myso就產生了我們就可以在程序中調用了如果想讓系統所有用戶都可以使用則應以root用戶登錄系統將這個庫拷貝到/lib目錄下(命令cp myso /lib)或者在/lib目錄下建個符號連接即可(命令ln s `pwd`/myso /lib)
  LINUX下動態鏈接庫的使用
   重要的dlfcnh頭文件
  LINUX下使用動態鏈接庫源程序需要包含dlfcnh頭文件此文件定義了調用動態鏈接庫的函數的原型下面詳細說明一下這些函數
   dlerror
  原型為: const char *dlerror(void);
  當動態鏈接庫操作函數執行失敗時dlerror可以返回出錯信息返回值為NULL時表示操作函數執行成功
   dlopen
  原型為: void *dlopen (const char *filename int flag);
  dlopen用於打開指定名字(filename)的動態鏈接庫並返回操作句柄
  filename: 如果名字不以/開頭則非絕對路徑名將按下列先後順序查找該文件
  () 用戶環境變量中的LD_LIBRARY值
  () 動態鏈接緩沖文件/etc/ldsocache
  () 目錄/lib/usr/lib
  flag表示在什麼時候解決未定義的符號(調用)取值有兩個:
  ) RTLD_LAZY : 表明在動態鏈接庫的函數代碼執行時解決
  ) RTLD_NOW : 表明在dlopen返回前就解決所有未定義的符號一旦未解決dlopen將返回錯誤
  dlopen調用失敗時將返回NULL值否則返回的是操作句柄
   dlsym : 取函數執行地址
  原型為: void *dlsym(void *handle char *symbol);
  dlsym根據動態鏈接庫操作句柄(handle)與符號(symbol)返回符號對應的函數的執行代碼地址由此地址可以帶參數執行相應的函數
  如程序代碼: void (*add)(int xint y); /* 說明一下要調用的動態函數add */
  add=dlsym(xxxsoadd); /* 打開xxxso共享庫取add函數地址 */
  add(); /* 帶兩個參數調用add函數 */
   dlclose : 關閉動態鏈接庫
  原型為: int dlclose (void *handle);
  dlclose用於關閉指定句柄的動態鏈接庫只有當此動態鏈接庫的使用計數為才會真正被系統卸載
   在程序中使用動態鏈接庫函數
   程序范例
  下面的程序裝載了動態鏈接庫myso並用getdategettime取得當前日期與時間後輸出
  
   /************************************/
   /* 文件名稱: dyc */
   /* 功能描述: 動態鏈接庫應用示范程序 */
   /* 程序編寫: 縱橫軟件制作中心雨亦奇 */
   /* 編寫時間: */
   /************************************/
  
   #include stdioh /* 包含標准輸入輸出文件 */
  
   #include
From:http://tw.wingwit.com/Article/program/Oracle/201311/17429.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.