When a program or application start on Linux, shared libraries are loaded. So if the shared library is installed properly in the system, all programs that start afterwards automatically use the new shared library. In managing your system’s applications, you need to understand libraries and, more specifically, shared libraries.
In this guide, we will look at how to manage shared libraries on Linux.
A collection of items, such as program functions is called system library. Self-contained code modules that perform a specific task within an application, such as opening and reading a data file are called functions.
There is an advantage of splitting functions into separate library files is that multiple applications that use the same functions can share the same library files. These files full of functions make it easier to distribute applications.
Linux supports two different types of libraries;
- Static libraries or Statically linked libraries
These are libraries which are loaded into an application when it is compiled.
- Shared libraries or Dynamic libraries
These are library functions which are loaded into memory and bound to the application when the program is launched.
On Linux/Unix systems, like application packages, library files have naming conventions. A shared library file uses the following filename format:
Locating Library Files
In locating library files, the system will search for the function’s library file in a specific order when a program is using a shared function in directories stored within;
- LD_LIBRARY_PATH environment variable
- Program’s PATH environment variable
- /etc/ld.so.conf.d/ folder
- /etc/ld.so.conf file
- /lib/ and /usr/lib/ folders
Note: The order of no. 3 & 4 may alternate on your system. The reason is because the /etc/ld.so.conf file loads configuration files from the /etc/ld.so.conf.d/ folder.
Displaying the /etc/ld.so.conf file contents on Linux:
$ cat /etc/ld.so.conf include /etc/ld.so.conf.d/*.conf
$ ls -1 /etc/ld.so.conf.d/ fakeroot-x86_64-linux-gnu.conf libc.conf x86_64-linux-gnu.conf
It is important to know that:
- The /lib*/ folders, such as /lib/ and /lib64/,are for libraries needed by system utilities that reside in the /bin/ and /sbin/ directories
- The /usr/lib*/ folders, such as /usr/lib/ and /usr/lib64/, are for libraries needed by additional software, such as database utilities like MariaDB.
Files within the /etc/ld.so.conf.d/ folder contains a shared library directory name and inside that directory are the shared library files needed by an application.
Looking at the /etc/ld.so.conf.d/ file contents on Ubuntu:
$ cat /etc/ld.so.conf.d/x86_64-linux-gnu.conf # Multiarch support /usr/local/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu
$ ls /usr/lib/x86_64-linux-gnu libpytalloc-util.cpython-38-x86-64-linux-gnu.so.2 libpytalloc-util.cpython-38-x86-64-linux-gnu.so.2.3.0 libsamba-policy.cpython-38-x86-64-linux-gnu.so.0 libsamba-policy.cpython-38-x86-64-linux-gnu.so.0.0.1
Loading Shared Libraries Dynamically
Dynamic linker also called dynamic linker/loader is responsible for finding the program’s needed library functions when a program is started. After they are located, the dynamic linker will copy them into memory and bind them to the program.
The dynamic linker executable has a name like ld.so and ld-linux.so* or you may use
locate command to find the right name based on your distribution, in my case it is Ubuntu distro.
Locating the dynamic linker executable on Ubuntu.
$ locate ld-linux /snap/core/10859/lib/ld-linux.so.2 /snap/core/10859/lib/i386-linux-gnu/ld-linux.so.2 /snap/core/10859/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /snap/core/10859/lib64/ld-linux-x86-64.so.2 /snap/core/10908/lib/ld-linux.so.2 /snap/core/10908/lib/i386-linux-gnu/ld-linux.so.2 /snap/core/10908/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /snap/core/10908/lib64/ld-linux-x86-64.so.2 /snap/core18/1932/lib/ld-linux.so.2 /snap/core18/1932/lib/i386-linux-gnu/ld-linux.so.2 /snap/core18/1932/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /snap/core18/1932/lib64/ld-linux-x86-64.so.2 /snap/core18/1988/lib/ld-linux.so.2 /snap/core18/1988/lib/i386-linux-gnu/ld-linux.so.2 /snap/core18/1988/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /snap/core18/1988/lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /usr/lib64/ld-linux-x86-64.so.2 /usr/share/man/man8/ld-linux.8.gz /usr/share/man/man8/ld-linux.so.8.gz
Once you have located the dynamic linker utility, you can use it to manually load a program and its libraries (it will run the program as well)
Example, On Ubuntu distribution using
ls command to list the contents of ~/Music directory.
$ /usr/lib64/ld-linux-x86-64.so.2 /usr/bin/ls ~/Music config THM
You find that I have config and THM files in my ~/Music directory
Managing the Library Cache
Library cache is a catalog of library directories and all the various libraries contained within them. The system reads this cache file to quickly find needed libraries when it is loading programs. This makes it much faster for loading libraries than searching through all the possible directory locations for a particular required library file.
When new libraries or library directories are added to the system, this library cache file must be updated. Thus,
ldconfig must be run every time configuration files are added or updated.
ldconfig has the following useful options:
--verbose, Display the library version numbers, the name of each directory, and the links that are created:
$ sudo ldconfig -v /usr/local/lib: /lib/x86_64-linux-gnu: libsndio.so.7.0 -> libsndio.so.7.0 libcups.so.2 -> libcups.so.2 libx264.so.155 -> libx264.so.155 libdv.so.4 -> libdv.so.4.0.3 libbd_part.so.2 -> libbd_part.so.2.0.0 libspice-client-gtk-3.0.so.5 -> libspice-client-gtk-3.0.so.5.0.0
In the example above, we see how
libsndio.so.7.0 is linked to the actual shared object file
--print-cache, Print the lists of directories and candidate libraries stored in the current cache:
$ sudo ldconfig -p 1005 libs found in cache `/etc/ld.so.cache' libzvbi.so.0 (libc6,x86-64) => /lib/x86_64-linux-gnu/libzvbi.so.0 libzvbi-chains.so.0 (libc6,x86-64) => /lib/x86_64-linux-gnu/libzvbi-chains.so.0 libzstd.so.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libzstd.so.1 libzip.so.5 (libc6,x86-64) => /lib/x86_64-linux-gnu/libzip.so.5 libz.so.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libz.so.1 libyelp.so.0 (libc6,x86-64) => /lib/x86_64-linux-gnu/libyelp.so.0 libyaml-0.so.2 (libc6,x86-64) => /lib/x86_64-linux-gnu/libyaml-0.so.2 libyajl.so.2 (libc6,x86-64) => /lib/x86_64-linux-gnu/libyajl.so.2 libx265.so.179 (libc6,x86-64) => /lib/x86_64-linux-gnu/libx265.so.179
Now we can see how the cache uses the fully qualified soname (shared object name) of the links:
$ sudo ldconfig -p |grep libfuse libfuse.so.2 (libc6,x86-64) => /lib/x86_64-linux-gnu/libfuse.so.2
Let’s now long list
/lib/x86_64-linux-gnu/libfuse.so.2, we will find the reference to the actual shared object file
libfuse.so.2.9.9 which is stored in the same directory:
$ ls -l /lib/x86_64-linux-gnu/libfuse.so.2 lrwxrwxrwx 1 root root 16 Sep 1 2020 /lib/x86_64-linux-gnu/libfuse.so.2 -> libfuse.so.2.9.9
We can add new paths for shared libraries temporarily using
LD_LIBRARY_PATH i.e to add
/usr/local/mynewlib to the library path in the current shell session, use:
Now let’s check the new added library,
$ echo $LD_LIBRARY_PATH /usr/local/mynewlib
/usr/local/mynewlib permanently to the library path in the current shell session and have it exported to all child processes spawned from that shell, use;
$ export LD_LIBRARY_PATH=/usr/local/mynewlib
To remove the
LD_LIBRARY_PATH environment variable, use;
$ unset LD_LIBRARY_PATH
Searching Dependencies of a Particular Executable
To look up the shared libraries required by a specific program, use the
ldd command followed by the absolute path to the program. The output shows the path of the shared library file as well as the hexadecimal memory address at which it is loaded:
$ ldd /usr/bin/ssh linux-vdso.so.1 (0x00007ffffe1c5000) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fef16f5e000) libcrypto.so.1.1 => /lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007fef16c88000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fef16c82000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fef16c66000) libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fef16c4a000) libgssapi_krb5.so.2 => /lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007fef16bfd000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fef16a09000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007fef16979000) /lib64/ld-linux-x86-64.so.2 (0x00007fef17065000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fef16956000) libkrb5.so.3 => /lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007fef16879000) libk5crypto.so.3 => /lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007fef16848000) libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007fef16841000) libkrb5support.so.0 => /lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007fef16830000) libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007fef16829000)
We also use
ldd to search for the dependencies of a shared object:
$ ldd /lib/x86_64-linux-gnu/libkrb5support.so.0 linux-vdso.so.1 (0x00007ffd2b3e0000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f77ce49a000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f77ce2a8000) /lib64/ld-linux-x86-64.so.2 (0x00007f77ce4c5000)
ldd prints the unused direct dependencies (if they exist).
$ ldd -u /usr/bin/ssh
The reason for unused dependencies is related to the options used by the linker when building the binary. Although the program does not need an unused library, it was still linked and labelled as
NEEDED in the information about the object file. You can investigate this using commands such as
Note: Sometimes a library is dependent on another library. So when you are troubleshooting a missing library file, you may need to use the
ldd command on the libraries listed for the application in order to get to the root of the problem.
This is the the of our guide on how to Manage Shared Libraries on Linux, I hope this guide has been helpful.
Here is a list of other articles you can also check: