您的位置:首页 > 其它

The shared library soname

2016-12-02 15:52 127 查看
下面引用一段英文原文


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:

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.

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.

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.

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:
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
version
identifier. 

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: 

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


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
symbolic
link
 to
either real
name or soname of most recent major
version of the library. 

More convenient to have it point
to soname. Why? 

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:
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


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


Build executable using
the linker name:

$ gcc -g -Wall -o ./prog prog.c -L. -ldemo


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:
Speed: Shared
libraries can reside in many different directories:
it could take the dynamic linker a long
time to search them


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:
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. 

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:
If LD_LIBRARY_PATH is
defined, then each of the colon-separated directories listed in its
value is searched in turn. 

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

/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文件管理项目的动态库版本,具体实施过程待实践。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐