14.4 Objective 4: Manage Shared
Libraries
When a
program is compiled under Linux, many of the functions
required by the program are linked from system libraries that handle disks, memory, and other
functions. For example, when printf( ) is used
in a program, the programmer doesn't provide the printf(
) source code, but instead expects that the system
already has a library containing such functions. When the
compiler needs to link the code for printf( ), it can
be found in a system library and copied into the executable. A
program that contains executable code from these libraries is
said to be statically linked
because it stands alone, requiring no additional code at
runtime.
Statically linked programs can have a few
liabilities. First, they tend to get large, because they
include executables for all of the library functions linked
into them. Also, memory is wasted when many different programs
running concurrently contain the same library functions. To
avoid these problems, many programs are dynamically linked. Such programs
utilize the same routines but don't contain the library code.
Instead, they are linked into the executable at runtime. This
dynamic linking process allows multiple programs to use the
same library code in memory and makes executable files
smaller. Dynamically linked libraries are shared among many
applications and are thus called shared libraries. A full discussion
of libraries is beyond the scope of the LPIC Level 1 exams.
However, a general understanding of some configuration
techniques is required.
14.4.1 Shared Library
Dependencies
Any program that is dynamically linked will
require at least a few shared libraries. If the required
libraries don't exist or can't be found, the program will fail
to run. This could happen, for example, if you attempt to run
an application written for the GNOME graphical environment but
haven't installed the required GTK+ libraries. Simply
installing the correct libraries should eliminate such
problems. The ldd utility can
be used to determine which libraries are necessary for a
particular executable.
Syntaxldd programs
Description
Display shared libraries required by
each of the programs listed on the command line. The
results indicate the name of the library and where the library
is expected to be in the filesystem.
Example
In Objective 3, a trivial executable called
hw was created. Despite its
small size, however, hw
requires two shared libraries: # ldd /home/jdean/hw
/home/jdean/hw:
libc.so.6 => /lib/libc.so.6 (0x40018000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
The bash shell
requires three shared libraries: # ldd /bin/bash
/bin/bash:
libtermcap.so.2 => /lib/libtermcap.so.2 (0x40018000)
libc.so.6 => /lib/libc.so.6 (0x4001c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
14.4.2 Linking Shared
Libraries
Dynamically linked
executables are examined at runtime by the shared object dynamic linker,
ld.so. This program looks for
dependencies in the executable being loaded and attempts to
satisfy any unresolved links to system-shared libraries. If
ld.socan't find a specified library, it fails, and the
executable won't run.
To illustrate this, let's assume that the
printit( ) function from the hw example in Objective 3 is moved to
a shared library instead of being compiled into the program.
The custom library is called libprintit.so and stored
in /usr/local/lib. hw is
reconfigured and recompiled to use the new library. By default,
ld.sodoesn't expect to look in /usr/local/lib
for libraries, and fails to find printit( ) at
runtime:
# ./hw
./hw: error in loading shared libraries: libprintit.so:
cannot open shared object file: No such file or directory
To find the new library, ld.so must be
instructed to look in /usr/local/lib. There are a few
ways to do this. One simple way is to add a colon-separated
list of directories to the shell environment variable
LD_LIBRARY_PATH, which will prompt ld.soto
look in any directories it finds there. However, this method
may not be appropriate for system libraries, because users
might not set their LD_LIBRARY_PATH correctly.
To make the search of /usr/local/lib
part of the default behavior for ld.so, files in the
new directory must be included in an index of library names
and locations. This index is /etc/ld.so.cache. It's a
binary file, which means it can be read quickly by
ld.so. To add the new library entry to the cache, its
directory is first added to the ld.so.conf file, which
contains directories to be indexed by the ldconfig utility.
Syntaxldconfig [options] lib_dirs
Description
Update the
ld.so cache file with shared
libraries specified on the command line in lib_dirs, in
trusted directories /usr/lib and /lib, and in
the directories found in /etc/ld.so.conf.
Frequently used options
- -p
-
Display the contents of the current cache
instead of recreating it.
- -v
-
Verbose mode. Display progress during
execution.
Example 1
Examine the contents of the ld.so
library cache: # ldconfig -p
299 libs found in cache `/etc/ld.so.cache' (version 1.7.0)
libzvt.so.2 (libc6) => /usr/lib/libzvt.so.2
libz.so.1 (libc6) => /usr/lib/libz.so.1
libz.so.1 (ELF) => /usr/i486-linux-libc5/lib/libz.so.1
libz.so (libc6) => /usr/lib/libz.so
libx11amp.so.0 (libc6) => /usr/X11R6/lib/libx11amp.so.0
libxml.so.0 (libc6) => /usr/lib/libxml.so.0
(... listing continues ...)
Example 2
Look for a specific library entry in the
cache: # ldconfig -p | grep "printit"
libprintit.so (libc6) => /usr/local/lib/libprintit.so
Example 3
Rebuild the cache: # ldconfig
After /usr/local/lib is added,
ld.so.conf might look like this: /usr/lib
/usr/i486-linux-libc5/lib
/usr/X11R6/lib
/usr/local/lib
Next, ldconfig
is run to include libraries found in /usr/local/lib in
/etc/ld.so.cache : # ldconfig
# ./hw
Hello, world
Now the hw
program can execute correctly because ld.so can find
libprintit.so in /usr/local/lib. It is important
to run ldconfig after any
changes in system libraries to be sure that the cache is
up-to-date.
|