>轉載請注明來源:飄零的代碼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條評論
主站蜘蛛池模板: 日本阿v视频高清在线 | 人人狠狠综合88综合久久 | 小视频在线观看免费 | 精品伊人久久久99热这里只 | 粉嫩粉嫩芽的虎白女18在线视频 | 亚洲视频在线观看网站 | 欧美精品一区在线 | 久久久久久久一区二区 | 欧美精品国产第一区二区 | 我的朋友丈夫 | 日韩中文字幕免费版 | 男人的天堂久久 | 国产精品美女久久久久久久久久久 | 久久国产精品99久久小说 | 美国一级免费视频 | a级欧美片免费观看 | 国产欧美日本 | 不卡国产一区二区三区四区 | 欧美日韩一区二区三区在线观看 | 亚洲一区二区色情苍井空 | 亚洲视频免费观看 | 国产美女精品 | 亚洲精品在线播放 | 久久综合丝袜长腿丝袜 | 国产福利99 | www.中文字幕 | 国产成人精品一区二区三区四区 | sese综合| 日本免费a视频 | 毛片99 | 成人免费无毒在线观看网站 | 伊人无码高清 | 日本亚洲a | 激情视频免费看 | 色婷婷久久久 | 国产精品亚洲va在线观看 | 中文字幕亚洲一区 | 天天噜天天干 | 成人精品久久久 | 婷婷成人综合 | 国产精品123区 |