linux动态库版本号管理

下面引用一段英文原文

The shared library soname

In the earlier example, we embedded the actual name (the real name) of the shared library in an executable file.

It is possible to create an alias, called the soname, which will be embedded in an executable file instead of the real name

At run-time, the dynamic linker will use the soname when searching for the library. 

The purpose of the soname is to provide a level of indirection.

  • At run-time, executable can use a version of the shared library that is different (but compatible) from that against which it was linked.

    The shared library soname (cont.)

    Here's how to use a soname:

    1. Specify soname when creating shared library:
      $ gcc -fPIC -c -Wall -g mod1.c mod2.c mod3.c $ gcc -shared -Wl,-soname,libbar.so -o libfoo.so \
                 mod1.o mod2.o mod3.o 
      -Wl,-soname,libbar.so instructs linker to mark the shared library  libfoo.so with the  soname  libbar.so.
    2. Create executable:


      $ gcc -g -Wall -o prog prog.c libfoo.so 
      Linker detects that  libfoo.so contains the  soname  libbar.so and embeds the latter name inside the executable.
    3. Run the program:
      $ LD_LIBRARY_PATH=. ./prog ./prog: error in loading shared libraries: 
      libbar.so: cannot open shared object file: 
      No such file or directory
      
      Dynamic linker cannot find anything named  libbar.so.
    4. Create a symbolic link from the soname to the real name of the library:
      $ ln -s libfoo.so libbar.so $ LD_LIBRARY_PATH=. ./prog Called mod1-x1
      Called mod2-x2
      

    At run-time this link can point to a version of the library which is different from the version against which linking was performed

    The shared library soname (cont.)

    This diagram shows the steps required in building a shared library, linking a program against it, and creating the requiredsoname symbolic link.

     

    The shared library soname (cont.)

    This diagram shows the steps that occur as the program is executed:

     

    Compatible Versus Incompatible Libraries

    We probably need to change a library over time.

    A new library version is said to be compatible with an existing library version if all of the following conditions hold true:

    • The semantics of each function in the library remain unchanged

      • All functions continue to produce same effect on global variables and returned arguments

      • All functions continue to return the same result values

      • Performance improvements and bug fixes (perhaps resulting in closer conformance to specified behavior) are compatible changes. 

    • No function in the library API is removed.
      New functions can be added.
    • The structures exported (i.e. allocated within and returned) by each function remain unchanged.
      Possible exception: new items may be added to the end of the existing structure

    If any of these conditions is violated, then the new library version is incompatible with the previous version.



    Shared library versions and naming

    • If a new version of a shared library is compatible with an existing library, we can make a new minor version of the library. 

    • If a new version of a shared library is incompatible with an existing library, we must make a new major version of the library. 

    • Constraint: it must be possible to continue running programs requiring the older version of the library. 

    • Solution: a naming convention is used for shared library real names and sonames.

    Shared library versions and naming (cont.)

    Real name

    Name of the file containing library code.

    Format: libname.so.major-id.minor-id

    • Major version identifier is a number which is sequentially incremented with each incompatible release of the library. 

    • Minor version identifier distinguishes different compatible minor versions of a library within the same major version.
      Usually either a number, or two numbers separated by a dot, with first number identifying  minor version, and second number indicating a patch level or  revision number within the minor version.

    Examples:

    libdemo.so.1.0.1
    libdemo.so.1.0.2
    libdemo.so.2.0.1
    libreadline.so.4.0
    

    Shared library versions and naming (cont.)

    soname

    Format: libname.so.major-id

    soname includes the same major version identifier as corresponding real name, but does not include minor versionidentifier. 

    Purpose: run-time loading is dependent only on major version number of the library 

    soname is created as a symbolic link (usually in same directory as real name).

    • The soname for each major library version points to most recent minor version

    • Since it is the soname (not the real name) that is embedded in executable by linker: 

      1. At any time, we can change soname symbolic link to point to a newer minor version

      2. Different major versions can co-exist and be accessed by the programs that require them.

    Examples of sonames (along with the real names to which they might be symbolically linked):

    libdemo.so.1        -> libdemo.so.1.0.2
    libdemo.so.2        -> libdemo.so.2.0.1
    libreadline.so.4    -> libreadline.so.4.0

    Shared library versions and naming (cont.)

    Linker name

    • Format: libname.so 

    • Purpose: allows us to construct version-independent link commands which automatically operate with the right (i.e. most up to date) version of the shared library. 

    • Created as a symbolic link to either real name or soname of most recent major version of the library. 

    • More convenient to have it point to sonameWhy? 

    • Examples:
      libdemo.so           -> libdemo.so.2
      libreadline.so       -> libreadline.so.4
      

    Shared library versions and naming (cont.)

    Relationships between shared library names



    Creating Shared Libraries Using Standard Naming Conventions

    We can create a shared library using standard naming conventions as follows:

    1. Create the shared library with real name libdemo.so.1.0.1 and soname libdemo.so.1.
      $ gcc -fPIC -g -c -Wall mod1.c mod2.c mod3.c $ gcc -shared -Wl,-soname,libdemo.so.1 -o libdemo.so.1.0.1 \
                mod1.o mod2.o mod3.o 
    2. Create symbolic links for the soname and linker name:
      $ ln -s libdemo.so.1.0.1 libdemo.so.1 $ ln -s libdemo.so.1 libdemo.so $ ls -l libdemo.so* | cut -c 1-11,55- # Verify the setup lrwxrwxrwx  libdemo.so -> libdemo.so.1
      lrwxrwxrwx  libdemo.so.1 -> libdemo.so.1.0.1
      -rwxr-xr-x  libdemo.so.1.0.1
      
    3. Build executable using the linker name:
      $ gcc -g -Wall -o ./prog prog.c -L. -ldemo 
    4. Run the program as usual:
      $ LD_LIBRARY_PATH=. ./prog Called mod1-x1
      Called mod2-x2

    Installing Shared Libraries

    • Production applications should not require the user to set LD_LIBRARY_PATH

    • Privileged users can install a shared library in one of the standard library directories

      • /usr/lib - directory in which most standard libraries are installed 

      • /lib - directory containing libraries required during system startup 

      • /usr/local/lib non-standard or experimental libraries should be installed here;
        Also useful if  /usr/lib is a network mount shared among multiple systems, and we want to install a library locally.
      or in one of the directories listed in /etc/ld.so.conf.【注:linux版本如有“/etc/ld.so.conf.d目录”也可以将my.conf这样的配置文件放在/etc/ld.so.conf.d目录下, my.conf的内容格式为 /ldddir/dir】 

    • After installation, symbolic links for soname and linker name must be created, as relative links in the same directory.

    ldconfig(8)

    ldconfig(8) addresses two potential problems with shared libraries:

    1. Speed: Shared libraries can reside in many different directories: it could take the dynamic linker a long time to search them

    2. Manually keeping sonames symlinks up to date is error-prone as new versions of libraries are installed, or old versions are removed.

    ldconfig solves these problems by:

    1. Creating a cache file:
      ldconfig  searches for latest major library versions in: 

      • all of the directories specified in /etc/ld.so.conf
      • /lib
      • /usr/lib

      and  updates a cache file, /etc/ld.so.cache, to contain a list of the latest major library versions, and their locations.
      Cache file is used by dynamic linker at run-time when resolving library names. 

    2. Automating the creation of sonames

      • ldconfig examines (the latest minor version of) each major version of each library to find the embedded soname, and 

      • creates a relative symbolic link for this soname, in the same directory as the library. 

    In order to work properly, ldconfig relies on the use of the standard naming convention for shared libraries (i.e.,libname.maj.min) 


    ldconfig(8) (cont.)

    Example - installing two different major versions of a library.

    We copy both versions into /usr/lib:

    # mv libdemo.so.1.0.1 libdemo.so.2.0.1 /usr/lib # cd /usr/lib 

    We run ldconfig to update the dynamic linker cache:

    # ldconfig -v | grep libdemo libdemo.so.1 -> libdemo.so.1.0.1 (changed)
            libdemo.so.2 -> libdemo.so.2.0.1 (changed)
    
    • (We use grep to eliminate other output from ldconfig.)

    Then we manually create the linker name:

    # ln -s libdemo.so.2 libdemo.so 


    To install a new 2.x minor version:

    # mv libdemo.so.2.0.2 /usr/lib # cd /usr/lib # ldconfig -v | grep libdemo libdemo.so.1 -> libdemo.so.1.0.1
            libdemo.so.2 -> libdemo.so.2.0.2 (changed)
    

    The ldconfig command effectively also updates linker name...


    ldconfig(8) (cont.)

    • ldconfig should be run whenever a new library is installed or an existing library is updated or removed

    • ldconfig -p shows the current contents of the cache. 


    Upgrading Shared Libraries

    Note: A new major or minor version of a library can be installed, even while running programs are making use of an existing version.

    Example - upgrading a shared library with a new minor version (1.0.2):

    # gcc -fPIC -g -c -Wall mod1.c mod2.c mod3.c # gcc -shared -Wl,-soname,libdemo.so.1 -o libdemo.so.1.0.2 \
            mod1.o mod2.o mod3.o # mv libdemo.so.1.0.2 /usr/lib # ldconfig -v | grep libdemo libdemo.so.1 -> libdemo.so.1.0.2 (changed)
    

    Assuming the linker name was already correctly set up, we do not need to modify it.

    Then upgrading to a new major version (2.0.1):

    # gcc -fPIC -g -c -Wall mod1.c mod2.c mod3.c # gcc -shared -Wl,-soname,libdemo.so.2 -o libdemo.so.2.0.1 \
            mod1.o mod2.o mod3.o # mv libdemo.so.2.0.1 /usr/lib # ldconfig -v | grep libdemo libdemo.so.1 -> libdemo.so.1.0.2
            libdemo.so.2 -> libdemo.so.2.0.1 (changed)      
    # cd /usr/lib # ln -sf libdemo.so.2 libdemo.so 

    ldconfig automatically creates a soname symbolic link, but we must manually update the linker name symbolic link. 


    Finding Shared Libraries at Run-time

    The dynamic linker searches for shared libraries in the following order:

    1. If LD_LIBRARY_PATH is defined, then each of the colon-separated directories listed in its value is searched in turn. 

    2. /etc/ld.so.cache is checked to see if it contains an entry for the library. 

    3. /lib and /usr/lib are searched (in that order).


    英文通俗易懂,大致总结一下:
    1.gcc编译编译选项-soname 为实际库文件(libsoname.so.major.minor)生成的别名,这个别名 libname.so.major,别名存放在 实际库文件的头部,执行readelf -d  libsoname.so.major.minor命令可以看到“0x0000000e (SONAME)                     Library soname: [libname.so.major]”

    2.执行ldconfig -n /current_dir命令,ldconfig会去读取 /curr ent_dir目录下所有动态库文件中(SONAME)信息,并生成指向各动态库文件的链接文件,链接文件的名字为相应 (SONAME)字段值(libname.so.major)。

    3.如果/current_dir被加入到/etc/ld.so.conf或/etc/ld.so.conf.d/中,则执行ldconfig -v命令可生成/current_dir目录下所有的SONAME链接文件并查看繁多的链接信息。

    4.连接器(linker)通过SONAME字段值( libname.so.major)在用户指定的路径查找链接 libname.so.major

    5.手动指定 libname.so --> libname.so.major,控制程序(progam)链接的 实际库文件( libsoname.so.major.minor),在/current_dir目录下我们会看到形如,
    libname.so  -->  libname.so.major
    libname.so.major -->  libname.so.major.minor
    的链接,其中仅
    libname.so.major.minor为规则文件。

    6.动态库的主、次版本号利用如下的一套约定即可实现动态库的版本管理。
    a.新生成库实际文件libname.so.major.minor,当
    库中函数接口未变化(更新不影响相关模块)主版本号major不改变,次版本号     minor加1。
    b. 库中函数接口变化(更新影响相关模块 )主版本号major加1 ,次版本号从0开始增加。
    c.当出现新旧版本共存情况
        libname.so.1 --> libname.so.1.2
        libname.so.2--> libname.so.2.0
    时需用户通过手动建立链接(libname.so链接libname.so.1还是libname.so.2),决定程序链接动态库。

    7.实际项目中可通过Makefile文件管理项目的动态库版本,具体实施过程待实践。


from: http://blog.chinaunix.net/uid-24907956-id-3979339.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值