分类: LINUX
2013-11-06 17:55:39
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.
Here's how to use a soname:
-Wl,-soname,libbar.so instructs linker to mark the shared library libfoo.so with the soname libbar.so.$ 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
Linker detects that libfoo.so contains the soname libbar.so and embeds the latter name inside the executable.$ gcc -g -Wall -o prog prog.c libfoo.so
Dynamic linker cannot find anything named libbar.so.$ LD_LIBRARY_PATH=. ./prog ./prog: error in loading shared libraries: libbar.so: cannot open shared object file: No such file or directory
$ 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.
This diagram shows the steps required in building a shared library, linking a program against it, and creating the requiredsoname symbolic link.
This diagram shows the steps that occur as the program is executed:
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:
New functions can be added.
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.
Name of the file containing library code.
Format: libname.so.major-id.minor-id
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
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).
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
libdemo.so -> libdemo.so.2 libreadline.so -> libreadline.so.4
We can create a shared library using standard naming conventions as follows:
$ 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
$ 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
$ gcc -g -Wall -o ./prog prog.c -L. -ldemo
$ LD_LIBRARY_PATH=. ./prog Called mod1-x1 Called mod2-x2
Also useful if /usr/lib is a network mount shared among multiple systems, and we want to install a library locally.
ldconfig(8) addresses two potential problems with shared libraries:
ldconfig solves these problems by:
ldconfig searches for latest major library versions in:Cache file is used by dynamic linker at run-time when resolving library names.
- 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.
In order to work properly, ldconfig relies on the use of the standard naming convention for shared libraries (i.e.,libname.maj.min)
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)
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...
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.
The dynamic linker searches for shared libraries in the following order: