Chinaunix首页 | 论坛 | 博客
  • 博客访问: 132967
  • 博文数量: 41
  • 博客积分: 15
  • 博客等级: 民兵
  • 技术积分: 65
  • 用 户 组: 普通用户
  • 注册时间: 2012-12-11 16:17
文章分类
文章存档

2017年(1)

2016年(5)

2015年(8)

2014年(13)

2013年(10)

2012年(4)

我的朋友

分类: LINUX

2015-10-22 14:22:47

下面引用一段英文原文

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会去读取/current_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文件管理项目的动态库版本,具体实施过程待实践。

阅读(1664) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~