Tuesday, September 6, 2016

Managing Shared Libraries

In addition to checking for software package dependencies, you may also need to verify that your system is configured properly to access the libraries an application needs to run. In this part of the chapter, you will learn how to do this. The following topics are addressed:

•      How shared libraries work
•      Managing shared library dependencies

Let’s begin by discussing how shared libraries work.

How Shared Libraries Work
On Linux, applications running on the system can share code elements called shared libraries.

 This is very useful. Shared libraries make it such that software developers don’t have to reinvent the wheel each time they write a new program.

If you think about it, many functions are commonly used across many programs. For example, the process for opening a file, saving a file, and closing an open file are the same no matter what application is being used. Without shared libraries, programmers would have to include the code for completing these basic tasks in each application they write. What a waste of time and resources!

Instead, with shared libraries, software developers can focus on the code elements that are unique to the individual application.
For common elements that are shared across applications, they can simply link to the prewritten code in a shared library and not worry about rewriting the code.

Using shared libraries has many benefits. Obviously, it dramatically speeds up development time. It also makes the programs being written smaller and leaner.

There are two types of shared libraries on Linux:

•      Dynamic
Dynamic shared libraries exist as files in the Linux file system. Programmers simply insert links to the functions in these shared libraries in their program code. The functions are called from the dynamic shared libraries when the program is run, not integrated into the program itself. A configuration file on the system contains a list of installed dynamic shared libraries and where they are located in the file system. Using dynamic shared libraries decreases the overall size of the executable after it’s compiled.

However, they do create a dependency issue. If the program calls a function from a dynamic shared library that isn’t installed on the system (or has become unavailable for some reason), the application will malfunction.

•      Static
In contrast to dynamic shared libraries, static shared libraries are linked statically into the program when it’s compiled. In essence, with static libraries, the actual code elements for the functions called are integrated directly into the application itself.
Obviously, this results in larger applications. However, it has the advantage of making the application independent of having the shared libraries installed on the system where it is running, as is the case with dynamic libraries.

Which type is best? It depends on the application. Most applications you will use on a day-to-day basis use dynamic shared libraries. This allows them to provide a lot of functionality with a relatively small footprint on the hard drive.

However, there are many applications that use static libraries, especially applications that are designed to help you rescue a malfunctioning system. Instead of linking to dynamic shared libraries (which may not be available in a system rescue scenario), these applications are completely self-contained and can run in a minimal Linux environment.

Shared library files use a special naming format to help you identify the type of shared library it is. This syntax is as follows:

libname.type.version

Notice that the filename of all shared libraries starts with lib.
 It is followed by the name of the shared library. The type part of the filename identifies the type of shared library. The characters “so” here indicate the file is a dynamic shared library, whereas “a” indicates the file is a static library. The version part of the filename specifies the version number of the library. For example, libfreetype.so.6.4.0 is a dynamic shared library.
With this in mind, let’s discuss how you manage shared library dependencies.


Managing Shared Library Dependencies
As noted earlier, Linux uses a configuration file to tell applications running on the system where they can find the dynamic shared library files on the system. Using this type of configuration provides application developers with a degree of independence. They don’t have to worry about where the shared libraries will reside when their programs are run. They let the configuration file tell the program where they are, wherever that happens to be on a particular Linux system.

The dynamic shared library configuration file is /etc/ld.so.conf. Here is a sample file:

openSUSE:/etc # cat ld.so.conf
/usr/X11R6/lib64/Xaw3d
/usr/X11R6/lib64
/usr/lib64/Xaw3d
/usr/X11R6/lib/Xaw3d
/usr/X11R6/lib
/usr/lib/Xaw3d
/usr/x86_64-suse-linux/lib
/usr/local/lib
/opt/kde3/lib
/lib64
/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/opt/kde3/lib64
include /etc/ld.so.conf.d/*.conf


As you can see in this example, the file simply contains a list of paths in the file system where shared library files are stored. Applications that are linked to functions in these files can search through these paths to locate the appropriate libraries.


The /lib/ and /usr/lib/ directories are always assumed to contain shared libraries, so they aren’t listed in the /etc/ld.so.conf file.


To view a list of all shared libraries available on your Linux system, enter ldconfig –p
at the shell prompt. Here is an example:

openSUSE:~ # ldconfig –p
1423 libs found in cache '/etc/ld.so.cache'
      libzypp.so.706 (libc6,x86-64) => /usr/lib64/libzypp.so.706
      libzio.so.0 (libc6,x86-64) => /usr/lib64/libzio.so.0
      libz.so.1 (libc6,x86-64) => /lib64/libz.so.1
      libz.so.1 (libc6) => /lib/libz.so.1
      libz.so (libc6,x86-64) => /usr/lib64/libz.so
      liby2util.so.4 (libc6,x86-64) => /usr/lib64/liby2util.so.4
      liby2.so.2 (libc6,x86-64) => /usr/lib64/liby2.so.2
      libyui.so.3 (libc6,x86-64) => /usr/lib64/libyui.so.3
      libycpvalues.so.3 (libc6,x86-64) => /usr/lib64/libycpvalues.so.3


You can also view the shared libraries required by a specific application using the ldd command. The syntax is

Ldd –v executable_filename

For example, if you wanted to see what shared libraries are required by the ip command (which is used to manage network connections), you would enter

ldd –v /sbin/ip

at the shell prompt.


An example is shown next:

openSUSE:~ # ldd -v /sbin/ip
      linux-vdso.so.1 =>  (0x00007fffe4ab2000)
      libdl.so.2 => /lib64/libdl.so.2 (0x00007f7c07e7d000)
      libc.so.6 => /lib64/libc.so.6 (0x00007f7c07b1d000)
      /lib64/ld-linux-x86-64.so.2 (0x00007f7c08081000)
Version information:
      /sbin/ip:
          libdl.so.2 (GLIBC_2.2.5) => /lib64/libdl.so.2
          libc.so.6 (GLIBC_2.7) => /lib64/libc.so.6
          libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6


One of the key uses for the ldd command is to check for shared library dependencies. It determines whether all of the libraries required by the application in question have been installed. If they have, you won’t see any error messages, as shown in the preceding example.

If a library file is missing, an error message will be displayed. You can then locate and install the missing library and all will be well with the world.

So, how does an application know which directories to look in when trying to locate a shared library? The applications don’t actually check the /etc/ld.so.conf conf file. Instead, they check the library cache and the LD_LIBRARY_PATH environment variable.

The library cache is /etc/ld.so.cache. This file contains a list of all the system libraries and is refreshed when the system is initially booted.
This is key. If you add a new dynamic library directory to the /etc/ld.so.conf file, you’ll be very frustrated when you try to run the applications that are linked to the libraries in this directory.
That’s because the library cache hasn’t been updated with the new information. To fix this, you have two options:

OPTIONS To UPDATE SHARED LIBRARIES:

A:   
Use ldconfig
. The ldconfig command is used to rebuild the library cache manually.

B:    Set LD_LIBRARY_PATH
. You can also add the path to the LD_LIBRARY_PATH environment variable. You probably want to add the new path to the end of the list of directories that may already exist in the variable, so you should use the following commands:

Set LD_LIBRARY_PATH=$LD_LIBRARY_PATH; new_path

export LD_LIBRARY_PATH

Generally speaking, the first option is the preferred one. This ensures the shared libraries are always available to the applications that need them, even if the system is rebooted.

I usually set the value of LD_LIBRARY_PATH only in situations where I have two versions of the same shared library installed in different directories and I want to use one version over the other.


Exercise 8-6: Working with Shared Libraries
In this exercise, you will practice managing shared libraries. You can perform this exercise using the virtual machine that comes with this book. Run snapshot 8-3 for the correctly configured environment.


Complete the following:

1. With your system running, open a terminal session.

2. If necessary, change to your root user account by entering
su – followed by your root user’s password.

3.
View the shared libraries used by the ping executable on your system by entering ldd –v /bin/ping at the shell prompt. You should see that ping requires the libc.so.6 shared library.

4. Find the location of the lib64/libc.so.6 library file on your system by entering find / –name libc.so.6 at the shell prompt. On a 32-bit system, you should see that the file resides in /lib. On a 64-bit system, it probably resides in /lib64.

5. View your system’s library cache by entering ldconfig –p at the shell prompt.

6. Rebuild your library cache by entering ldconfig –v at the shell prompt


No comments:

Post a Comment