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

日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

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

系統(tǒng) 2279 0

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

學習Linux共享庫動態(tài)加載緣于一個生產(chǎn)環(huán)境升級apache so文件常見錯誤操作:apache在運行中直接cp覆蓋目標so文件,一段時間后錯誤日志里面出現(xiàn)關(guān)鍵詞: Segmentation fault (段錯誤) ,一個個worker進程就這樣漸漸退出,最后無法處理HTTP請求。
首先了解一下共享庫的創(chuàng)建, 源文件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
                
                "
              
              
                )
              
              
                ;
              
              
                }
              
            

執(zhí)行g(shù)cc -fPIC -shared -o libtest.so test.c 會生成共享庫文件 libtest.so
參數(shù)含義:
-fPIC/-fpic: Compiler directive to output position independent code, a characteristic required by shared libraries. 創(chuàng)建共享庫必須的參數(shù)
-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
              
              
                ;
              
              
                }
              
            

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

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

接下來是主角:動態(tài)加載,源文件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
              
              
                ;
              
              
                }
              
            

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

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

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

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

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

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


12.5更新:
今天咨詢了維揚同學,可以用strace觀察程序運行期間的系統(tǒng)調(diào)用,發(fā)現(xiàn)有不少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只讀映射之后寫入(覆蓋)文件有關(guān)?
詳見續(xù)篇 《為何cp覆蓋進程的動態(tài)庫(so)會導致coredump》

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

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


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 文登市| 会同县| 长岭县| 高邑县| 广元市| 柳林县| 惠州市| 通化县| 高唐县| 蒙城县| 百色市| 三台县| 陈巴尔虎旗| 雷山县| 高安市| 宁晋县| 古蔺县| 连江县| 庄浪县| 金湖县| 大方县| 宁晋县| 南和县| 白山市| 通河县| 志丹县| 崇明县| 南乐县| 安远县| 邹城市| 江油市| 禹城市| 明水县| 体育| 普洱| 万盛区| 青岛市| 石景山区| 石嘴山市| 文山县| 清河县|