In the examples up to now, we created a shared library in a user-private directory, and then used the LD_LIBRARY_PATH
environment variable to ensure that the dynamic linker searched that directory. Both privileged and unprivileged users may use this technique. However, this technique should not be employed in production applications. More usually, a shared library and its associated symbolic links are installed in one of a number of standard library directories, in particular, one of the following:
/usr/lib
, the directory in which most standard libraries are installed;
/lib
, the directory into which libraries required during system startup should be installed (since, during system startup, /usr/lib
may not be mounted yet);
/usr/local/lib
, the directory into which nonstandard or experimental libraries should be installed (placing libraries in this directory is also useful if /usr/lib
is a network mount shared among multiple systems and we want to install a library just for use on this system); or
one of the directories listed in /etc/ld.so.conf
(described shortly).
In most cases, copying a file into one of these directories requires superuser privilege.
After installation, the symbolic links for the soname and linker name must be created, usually as relative symbolic links in the same directory as the library file. Thus, to install our demonstration library in /usr/lib
(whose permissions only allow updates by root), we would do the following:
$su
Password: #mv libdemo.so.1.0.1 /usr/lib
#cd /usr/lib
#ln -s libdemo.so.1.0.1 libdemo.so.1
#ln -s libdemo.so.1 libdemo.so
The last two lines in this shell session create the soname and linker name symbolic links.
The ldconfig(8) program addresses two potential problems with shared libraries:
Shared libraries can reside in a variety of directories. If the dynamic linker needed to search all of these directories in order to find a library, then loading libraries could be very slow.
As new versions of libraries are installed or old versions are removed, the soname symbolic links may become out of date.
The ldconfig program solves these problems by performing two tasks:
It searches a standard set of directories and creates or updates a cache file, /etc/ld.so.cache
, to contain a list of the (latest minor versions of each of the) major library versions in all of these directories. The dynamic linker in turn uses this cache file when resolving library names at run time. To build the cache, ldconfig searches the directories specified in the file /etc/ld.so.conf
and then /lib
and /usr/lib
. The /etc/ld.so.conf
file consists of a list of directory pathnames (these should be specified as absolute pathnames), separated by newlines, spaces, tabs, commas, or colons. In some distributions, the directory /usr/local/lib
is included in this list. (If not, we may need to add it manually.)
The command ldconfig -p displays the current contents of /etc/ld.so.cache
.
It examines the latest minor version (i.e., the version with the highest minor number) of each major version of each library to find the embedded soname and then creates (or updates) relative symbolic links for each soname in the same directory.
In order to correctly perform these actions, ldconfig expects libraries to be named according to the conventions described earlier (i.e., library real names include major and minor identifiers that increase appropriately from one library version to the next).
By default, ldconfig performs both of the above actions. Command-line options can be used to selectively inhibit either action: the -N option prevents rebuilding of the cache, and the -X option inhibits the creation of the soname symbolic links. In addition, the -v (verbose) option causes ldconfig to display output describing its actions.
We should run ldconfig whenever a new library is installed, an existing library is updated or removed, or the list of directories in /etc/ld.so.conf
is changed.
As an example of the operation of ldconfig, suppose we wanted to install two different major versions of a library. We would do this as follows:
$su
Password: #mv libdemo.so.1.0.1 libdemo.so.2.0.0 /usr/lib
#ldconfig -v | grep libdemo
libdemo.so.1 -> libdemo.so.1.0.1 (changed) libdemo.so.2 -> libdemo.so.2.0.0 (changed)
Above, we filter the output of ldconfig, so that we see just the information relating to libraries named libdemo
.
Next, we list the files named libdemo
in /usr/lib
to verify the setup of the soname symbolic links:
#cd /usr/lib
#ls -l libdemo* | awk '{print $1, $9, $10, $11}'
lrwxrwxrwx libdemo.so.1 -> libdemo.so.1.0.1 -rwxr-xr-x libdemo.so.1.0.1 lrwxrwxrwx libdemo.so.2 -> libdemo.so.2.0.0 -rwxr-xr-x libdemo.so.2.0.0
We must still create the symbolic link for the linker name, as shown in the next command:
# ln -s libdemo.so.2 libdemo.so
However, if we install a new 2.x minor version of our library, then, since the linker name points to the latest soname, ldconfig has the effect of also keeping the linker name up to date, as the following example shows:
#mv libdemo.so.2.0.1 /usr/lib
#ldconfig -v | grep libdemo
libdemo.so.1 -> libdemo.so.1.0.1 libdemo.so.2 -> libdemo.so.2.0.1 (changed)
If we are building and using a private library (i.e., one that is not installed in one of the standard directories), we can have ldconfig create the soname symbolic link for us by using the -n option. This specifies that ldconfig should process only libraries in the directories on the command line and should not update the cache file. In the following example, we use ldconfig to process libraries in the current working directory:
$gcc -g -c -fPIC -Wall mod1.c mod2.c mod3.c
$gcc -g -shared -Wl,-soname,libdemo.so.1 -o libdemo.so.1.0.1 \
mod1.o mod2.o mod3.o
$/sbin/ldconfig -nv .
.: libdemo.so.1 -> libdemo.so.1.0.1 $ls -l libdemo.so* | awk '{print $1, $9, $10, $11}'
lrwxrwxrwx libdemo.so.1 -> libdemo.so.1.0.1 -rwxr-xr-x libdemo.so.1.0.1
In the above example, we specified the full pathname when running ldconfig, because we were using an unprivileged account whose PATH
environment variable did not include the /sbin
directory.