>轉載請注明來源:飄零的代碼piao2010’sblog,謝謝!^_^>>本文鏈接地址:Linux共享庫(so)動態加載和升級學習Linux共享庫動態加載緣于一個生產環境升級apacheso文件常見錯誤操作:apache在運行中直接cp覆蓋目標so文件,一段時間后錯誤日志里面出現關鍵詞:Segmentationfault(段錯誤),一個個worker進程就這樣漸漸退出,最后無法處理HTTP請求。首先了解一下共享庫的創建,源文件test.c?ViewCod" />

欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Linux共享庫(so)動態加載和升級

系統 2030 0

>>轉載請注明來源: 飄零的代碼 piao2010 ’s blog ,謝謝!^_^
>>本文鏈接地址: Linux共享庫(so)動態加載和升級

學習Linux共享庫動態加載緣于一個生產環境升級apache so文件常見錯誤操作:apache在運行中直接cp覆蓋目標so文件,一段時間后錯誤日志里面出現關鍵詞: Segmentation fault (段錯誤) ,一個個worker進程就這樣漸漸退出,最后無法處理HTTP請求。
首先了解一下共享庫的創建, 源文件test.c

              
                #include<stdio.h>
              
              
                #include<unistd.h>
              
              

?


              
                void
              
               test1
              
                (
              
              
                void
              
              
                )
              
              
                {
              
              
                
                  printf
                
              
              
                (
              
              
                "This is do test1
                
                  \n
                
                "
              
              
                )
              
              
                ;
              
              

    sleep
              
                (
              
              
                10
              
              
                )
              
              
                ;
              
              
                
                  printf
                
              
              
                (
              
              
                "End of test1
                
                  \n
                
                "
              
              
                )
              
              
                ;
              
              
                }
              
              

?


              
                void
              
               test2
              
                (
              
              
                void
              
              
                )
              
              
                {
              
              
                
                  printf
                
              
              
                (
              
              
                "This is do test2
                
                  \n
                
                "
              
              
                )
              
              
                ;
              
              

    sleep
              
                (
              
              
                10
              
              
                )
              
              
                ;
              
              
                
                  printf
                
              
              
                (
              
              
                "End of test2
                
                  \n
                
                "
              
              
                )
              
              
                ;
              
              
                }
              
            

執行gcc -fPIC -shared -o libtest.so test.c 會生成共享庫文件 libtest.so
參數含義:
-fPIC/-fpic: Compiler directive to output position independent code, a characteristic required by shared libraries. 創建共享庫必須的參數
-shared: Produce a shared object which can then be linked with other objects to form an executable.

然后使用共享庫:源文件main2.c

              
                #include <stdio.h>
              
              

?


              
                int
              
               main
              
                (
              
              
                )
              
              
                {
              
              

    test1
              
                (
              
              
                )
              
              
                ;
              
              

    test2
              
                (
              
              
                )
              
              
                ;
              
              
                return
              
              
                0
              
              
                ;
              
              
                }
              
            

動態庫鏈接:gcc -o main2 -L . -ltest main2.c 生成二進制程序main2
參數含義:
-L 指定動態庫目錄為當前目錄
-l 指定動態庫名test,不要寫libtest.so

執行main2程序發現報錯: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
原因是共享庫不在系統默認的路徑里面,可以在shell執行 export LD_LIBRARY_PATH=./ 添加當前路徑或者在 /etc/ld.so.conf 增加路徑并ldconfig生效
執行main2成功輸出:
This is do test1
End of test1
This is do test2
End of test2

接下來是主角:動態加載,源文件main.c

              
                #include <stdio.h>
              
              
                #include <dlfcn.h> /* 必須加這個頭文件 */
              
              

?


              
                int
              
               main
              
                (
              
              
                )
              
              
                {
              
              
                void
              
              
                *
              
              lib_handle
              
                ;
              
              
                void
              
              
                (
              
              
                *
              
              fn1
              
                )
              
              
                (
              
              
                void
              
              
                )
              
              
                ;
              
              
                void
              
              
                (
              
              
                *
              
              fn2
              
                )
              
              
                (
              
              
                void
              
              
                )
              
              
                ;
              
              
                char
              
              
                *
              
              error
              
                ;
              
              

?

   lib_handle 
              
                =
              
               dlopen
              
                (
              
              
                "libtest.so"
              
              
                ,
              
               RTLD_LAZY
              
                )
              
              
                ;
              
              
                if
              
              
                (
              
              
                !
              
              lib_handle
              
                )
              
              
                {
              
              

      fprintf
              
                (
              
              stderr
              
                ,
              
              
                "%s
                
                  \n
                
                "
              
              
                ,
              
               dlerror
              
                (
              
              
                )
              
              
                )
              
              
                ;
              
              
                return
              
              
                1
              
              
                ;
              
              
                }
              
              

?

   fn1 
              
                =
              
               dlsym
              
                (
              
              lib_handle
              
                ,
              
              
                "test1"
              
              
                )
              
              
                ;
              
              
                if
              
              
                (
              
              
                (
              
              error 
              
                =
              
               dlerror
              
                (
              
              
                )
              
              
                )
              
              
                !=
              
               NULL
              
                )
              
              
                {
              
              

      fprintf
              
                (
              
              stderr
              
                ,
              
              
                "%s
                
                  \n
                
                "
              
              
                ,
              
               error
              
                )
              
              
                ;
              
              
                return
              
              
                1
              
              
                ;
              
              
                }
              
              

?

   fn1
              
                (
              
              
                )
              
              
                ;
              
              

?

   fn2 
              
                =
              
               dlsym
              
                (
              
              lib_handle
              
                ,
              
              
                "test2"
              
              
                )
              
              
                ;
              
              
                if
              
              
                (
              
              
                (
              
              error 
              
                =
              
               dlerror
              
                (
              
              
                )
              
              
                )
              
              
                !=
              
               NULL
              
                )
              
              
                {
              
              

      fprintf
              
                (
              
              stderr
              
                ,
              
              
                "%s
                
                  \n
                
                "
              
              
                ,
              
               error
              
                )
              
              
                ;
              
              
                return
              
              
                1
              
              
                ;
              
              
                }
              
              

?

   fn2
              
                (
              
              
                )
              
              
                ;
              
              

?

   dlclose
              
                (
              
              lib_handle
              
                )
              
              
                ;
              
              

?

   
              
                return
              
              
                0
              
              
                ;
              
              
                }
              
            

接口函數介紹:
(1) dlopen
函數原型:void *dlopen(const char *libname,int flag);
功能描述:dlopen必須在dlerror,dlsym和dlclose之前調用,表示要將庫裝載到內存,準備使用。
如果要裝載的庫依賴于其它庫,必須首先裝載依賴庫。如果dlopen操作失敗,返回NULL值;如果庫已經被裝載過,則dlopen會返回同樣的句柄。
參數中的libname一般是庫的全路徑,這樣dlopen會直接裝載該文件;如果只是指定了庫名稱,在dlopen會按照下面的機制去搜尋:
a.根據環境變量LD_LIBRARY_PATH查找
b.根據/etc/ld.so.cache查找
c.查找依次在/lib和/usr/lib目錄查找。
flag參數表示處理未定義函數的方式,可以使用RTLD_LAZY或RTLD_NOW。RTLD_LAZY表示暫時不去處理未定義函數,先把庫裝載到內 存,等用到沒定義的函數再說;RTLD_NOW表示馬上檢查是否存在未定義的函數,若存在,則dlopen以失敗告終。

(2) dlerror
函數原型:char *dlerror(void);
功能描述:dlerror可以獲得最近一次dlopen,dlsym或dlclose操作的錯誤信息,返回NULL表示無錯誤。dlerror在返回錯誤信息的同時,也會清除錯誤信息。

(3) dlsym
函數原型:void *dlsym(void *handle,const char *symbol);
功能描述:在dlopen之后,庫被裝載到內存。dlsym可以獲得指定函數(symbol)在內存中的位置(指針)。
如果找不到指定函數,則dlsym會返回NULL值。但判斷函數是否存在最好的方法是使用dlerror函數,

(4) dlclose
函數原型:int dlclose(void *);
功能描述:將已經裝載的庫句柄減一,如果句柄減至零,則該庫會被卸載。如果存在析構函數,則在dlclose之后,析構函數會被調用。

編譯gcc -o main main.c -ldl 生成二進制程序main,執行輸出
This is do test1
End of test1
This is do test2
End of test2

到這里共享庫動態加載就介紹完了:)
最后模擬一下升級so故障:
在執行main的時候,趁sleep期間cp 另外的so文件覆蓋libtest.so,一會就出現Segmentation fault。
但是如果是mv 另外的so文件覆蓋libtest.so,則無此問題,或者先rm libtest.so 再cp/mv 也不會有問題,因此升級方法就是這兩種,當然最好是先停應用再升級。 至于原因,可以參考我前一篇博客 《Linux cp mv rm ln 命令對于 inode 和 dentry 的影響》


12.5更新:
今天咨詢了維揚同學,可以用strace觀察程序運行期間的系統調用,發現有不少mmap操作:

              省略前面

open
              
                (
              
              
                "/root/so/libtest.so"
              
              
                ,
              
               O_RDONLY
              
                )
              
              
                =
              
              
                3
              
              

read
              
                (
              
              
                3
              
              
                ,
              
              
                "
                
                  \177
                
                ELF
                
                  \1
                
                
                  \1
                
                
                  \1
                
                
                  \3
                
                
                  \0
                
                
                  \0
                
                
                  \0
                
                
                  \0
                
                
                  \0
                
                
                  \0
                
                
                  \0
                
                
                  \0
                
                
                  \3
                
                
                  \0
                
                
                  \3
                
                
                  \0
                
                
                  \1
                
                
                  \0
                
                
                  \0
                
                
                  \0
                
                
                  \240
                
                
                  \3
                
                
                  \0
                
                
                  \000
                
                4
                
                  \0
                
                
                  \0
                
                
                  \0
                
                "
              
              ...
              
                ,
              
              
                512
              
              
                )
              
              
                =
              
              
                512
              
              

brk
              
                (
              
              
                0
              
              
                )
              
              
                =
              
              
                0x8227000
              
              

brk
              
                (
              
              
                0x8248000
              
              
                )
              
              
                =
              
              
                0x8248000
              
              

fstat64
              
                (
              
              
                3
              
              
                ,
              
              
                {
              
              st_dev
              
                =
              
              makedev
              
                (
              
              
                253
              
              
                ,
              
              
                0
              
              
                )
              
              
                ,
              
               st_ino
              
                =
              
              
                17559
              
              
                ,
              
               st_mode
              
                =
              
              S_IFREG
              
                |
              
              
                0755
              
              
                ,
              
               st_nlink
              
                =
              
              
                1
              
              
                ,
              
               st_uid
              
                =
              
              
                0
              
              
                ,
              
               st_gid
              
                =
              
              
                0
              
              
                ,
              
               st_blksize
              
                =
              
              
                4096
              
              
                ,
              
               st_blocks
              
                =
              
              
                16
              
              
                ,
              
               st_size
              
                =
              
              
                4348
              
              
                ,
              
               st_atime


              
                =
              
              
                2012
              
              
                /
              
              
                05
              
              
                /
              
              
                13
              
              
                -
              
              
                14
              
              
                :
              
              
                13
              
              
                :
              
              
                18
              
              
                ,
              
               st_mtime
              
                =
              
              
                2012
              
              
                /
              
              
                05
              
              
                /
              
              
                13
              
              
                -
              
              
                14
              
              
                :
              
              
                13
              
              
                :
              
              
                01
              
              
                ,
              
               st_ctime
              
                =
              
              
                2012
              
              
                /
              
              
                05
              
              
                /
              
              
                13
              
              
                -
              
              
                14
              
              
                :
              
              
                13
              
              
                :
              
              
                01
              
              
                }
              
              
                )
              
              
                =
              
              
                0
              
              

mmap2
              
                (
              
              NULL
              
                ,
              
              
                5772
              
              
                ,
              
               PROT_READ
              
                |
              
              PROT_EXEC
              
                ,
              
               MAP_PRIVATE
              
                |
              
              MAP_DENYWRITE
              
                ,
              
              
                3
              
              
                ,
              
              
                0
              
              
                )
              
              
                =
              
              
                0x6e6000
              
              

mmap2
              
                (
              
              
                0x6e7000
              
              
                ,
              
              
                4096
              
              
                ,
              
               PROT_READ
              
                |
              
              PROT_WRITE
              
                ,
              
               MAP_PRIVATE
              
                |
              
              MAP_FIXED
              
                |
              
              MAP_DENYWRITE
              
                ,
              
              
                3
              
              
                ,
              
              
                0
              
              
                )
              
              
                =
              
              
                0x6e7000
              
              

close
              
                (
              
              
                3
              
              
                )
              
              
                =
              
              
                0
              
              

munmap
              
                (
              
              
                0xb7753000
              
              
                ,
              
              
                15020
              
              
                )
              
              
                =
              
              
                0
              
              

fstat64
              
                (
              
              
                1
              
              
                ,
              
              
                {
              
              st_dev
              
                =
              
              makedev
              
                (
              
              
                0
              
              
                ,
              
              
                11
              
              
                )
              
              
                ,
              
               st_ino
              
                =
              
              
                3
              
              
                ,
              
               st_mode
              
                =
              
              S_IFCHR
              
                |
              
              
                0620
              
              
                ,
              
               st_nlink
              
                =
              
              
                1
              
              
                ,
              
               st_uid
              
                =
              
              
                0
              
              
                ,
              
               st_gid
              
                =
              
              
                5
              
              
                ,
              
               st_blksize
              
                =
              
              
                1024
              
              
                ,
              
               st_blocks
              
                =
              
              
                0
              
              
                ,
              
               st_rdev
              
                =
              
              makedev
              
                (
              
              
                136
              
              
                ,
              
              
                0
              
              
                )
              
              
                ,
              
               st_

atime
              
                =
              
              
                2012
              
              
                /
              
              
                05
              
              
                /
              
              
                13
              
              
                -
              
              
                14
              
              
                :
              
              
                56
              
              
                :
              
              
                03
              
              
                ,
              
               st_mtime
              
                =
              
              
                2012
              
              
                /
              
              
                05
              
              
                /
              
              
                13
              
              
                -
              
              
                14
              
              
                :
              
              
                56
              
              
                :
              
              
                03
              
              
                ,
              
               st_ctime
              
                =
              
              
                2012
              
              
                /
              
              
                05
              
              
                /
              
              
                13
              
              
                -
              
              
                14
              
              
                :
              
              
                53
              
              
                :
              
              
                31
              
              
                }
              
              
                )
              
              
                =
              
              
                0
              
              

mmap2
              
                (
              
              NULL
              
                ,
              
              
                4096
              
              
                ,
              
               PROT_READ
              
                |
              
              PROT_WRITE
              
                ,
              
               MAP_PRIVATE
              
                |
              
              MAP_ANONYMOUS
              
                ,
              
              
                -
              
              
                1
              
              
                ,
              
              
                0
              
              
                )
              
              
                =
              
              
                0xb7756000
              
              

write
              
                (
              
              
                1
              
              
                ,
              
              
                "This is do test1
                
                  \n
                
                "
              
              
                ,
              
              
                17
              
              
                )
              
              
                =
              
              
                17
              
              

rt_sigprocmask
              
                (
              
              SIG_BLOCK
              
                ,
              
              
                [
              
              CHLD
              
                ]
              
              
                ,
              
              
                [
              
              
                ]
              
              
                ,
              
              
                8
              
              
                )
              
              
                =
              
              
                0
              
              

rt_sigaction
              
                (
              
              SIGCHLD
              
                ,
              
               NULL
              
                ,
              
              
                {
              
              SIG_DFL
              
                ,
              
              
                [
              
              
                ]
              
              
                ,
              
              
                0
              
              
                }
              
              
                ,
              
              
                8
              
              
                )
              
              
                =
              
              
                0
              
              

rt_sigprocmask
              
                (
              
              SIG_SETMASK
              
                ,
              
              
                [
              
              
                ]
              
              
                ,
              
               NULL
              
                ,
              
              
                8
              
              
                )
              
              
                =
              
              
                0
              
              

nanosleep
              
                (
              
              
                {
              
              
                10
              
              
                ,
              
              
                0
              
              
                }
              
              
                ,
              
              
                0xbfd63fe4
              
              
                )
              
              
                =
              
              
                0
              
              

write
              
                (
              
              
                1
              
              
                ,
              
              
                "End of test1
                
                  \n
                
                "
              
              
                ,
              
              
                13
              
              
                )
              
              
                =
              
              
                13
              
              

write
              
                (
              
              
                1
              
              
                ,
              
              
                "This is do test2
                
                  \n
                
                "
              
              
                ,
              
              
                17
              
              
                )
              
              
                =
              
              
                17
              
              

rt_sigprocmask
              
                (
              
              SIG_BLOCK
              
                ,
              
              
                [
              
              CHLD
              
                ]
              
              
                ,
              
              
                [
              
              
                ]
              
              
                ,
              
              
                8
              
              
                )
              
              
                =
              
              
                0
              
              

rt_sigaction
              
                (
              
              SIGCHLD
              
                ,
              
               NULL
              
                ,
              
              
                {
              
              SIG_DFL
              
                ,
              
              
                [
              
              
                ]
              
              
                ,
              
              
                0
              
              
                }
              
              
                ,
              
              
                8
              
              
                )
              
              
                =
              
              
                0
              
              

rt_sigprocmask
              
                (
              
              SIG_SETMASK
              
                ,
              
              
                [
              
              
                ]
              
              
                ,
              
               NULL
              
                ,
              
              
                8
              
              
                )
              
              
                =
              
              
                0
              
              

nanosleep
              
                (
              
              
                {
              
              
                10
              
              
                ,
              
              
                0
              
              
                }
              
              
                ,
              
              
                0xbfd63fe4
              
              
                )
              
              
                =
              
              
                0
              
              
                ---
              
               SIGSEGV 
              
                (
              
              Segmentation fault
              
                )
              
               @ 
              
                0
              
              
                (
              
              
                0
              
              
                )
              
              
                ---
              
              
                +++
              
               killed by SIGSEGV 
              
                +++
              
            

SIGSEGV信號估計和mmap只讀映射之后寫入(覆蓋)文件有關?
詳見續篇 《為何cp覆蓋進程的動態庫(so)會導致coredump》

參考資料:
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
http://hi.baidu.com/luoxsbupt/item/a9d346b7653a2771254b09bc

Linux共享庫(so)動態加載和升級


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日韩一级片在线免费观看 | 波多野结衣在线观看网址 | 欧美日韩中文在线观看 | 欧美成年性h版影视中文字幕 | 国内精品视频区在线2021 | 久久经典国产视频 | 国产精品无码人妻系列AV | 午夜剧场在线免费观看 | 在线一级片| 毛片999 | 亚洲综合久久伊人热 | 国产精品v欧美精品v日韩精品 | 99久久久精品国产一区二区 | 国产精品点击进入在线影院高清 | 男女激情啪啪 | 91tv在线观看 | 亚洲视频国产一区 | 国产99999| 99色综合| 国产成人综合网在线观看 | 欧美日韩第二页 | 日韩美女中文字幕 | 欧洲精品视频完整版在线 | snh48欧洲大片在线观看 | 欧美一级片在线看 | www.国产在线 | 欧美三级美国一级 | 国变精品美女久久久久av爽 | 黄网站免费在线观看 | 啪啪免费观看 | 成人国产精品免费观看视频 | www.youjizz.com久久| 亚洲精品午夜国产va久久成人 | 欧美不卡一区二区三区免 | 九色亚洲| 狠狠躁夜夜躁人人爽天天段 | 免费能直接在线观看黄的视频 | 久久电影精品久久99久久 | 狠狠干91 | 91欧美精品激情在线观看 | 亚洲精品a级 |