Creation and use of the Linux dynamic link library. So file

Source: Internet
Author: User

1. Introduction

Using GNU Tools How do we create our own library of programs under Linux? A "program function library" simply means that a file contains compiled code and data that can be compiled and used by other programs afterwards. The Library of program functions makes the whole program more modular, easier to recompile, and more convenient to upgrade.

The Library of program functions can be divided into 3 types: static function library (libraries), shared function library (GKFX libraries), dynamic load function library (dynamically loaded libraries):

1, the static function library , is added to the target program before the program executes;

2, shared function library , it is loaded into the program when the program starts, it can be shared by different programs, dynamic loading function library can be loaded at any time when the program is running.

3, dynamic function library , not another library function format, the difference is how the dynamic loading function library is used by programmers.

2. Static function library

The static function library is actually a simple set of common target files, which is generally used as a suffix of ". A" as a file. You can use the AR program to generate a static function library file. AR is the abbreviation of archiver. The static library is no longer used as much as it used to be, mainly because the shared library has a lot of advantages over it. Slowly, everyone likes to use the shared function library. However, in some places the static function library is still in use, one to maintain some of the previous program compatibility, and secondly, it is relatively simple to describe.

The static library function allows the programmer to link the program without recompiling the code, saving the time to recompile the code. However, in the face of such a fast computer today, the general program of the recompile will not take much time, so this advantage is not as obvious as it used to be. The static library is useful for developers, for example, if you want to use the functions you provide to others, but you want to keep the source code of the function secret, you can provide a static library file for others. In theory, the code generated using the ELF-formatted static library function can run faster than a program that uses a shared library of functions (or a dynamic library of functions), presumably 1-5%.

To create a static function library file, or to add a new target code to an existing static function library file, you can use the following command:

AR RCS my_library.a file1.o file2.o

In this example, the object code FILE1.O and FILE2.O are added to the My_library.a library file, and a new file is created if the my_library.a does not exist. When creating a static library function with the AR command, there are other parameters that can be selected to participate in the use of AR help. Don't repeat it here.

Once you have created a static function library, you can use it. You can use it as part of your compilation and connection process to generate your executable code. If you compile the executable code with GCC, you can specify the library function with the "-l" parameter. You can also use LD to do this, using its "-L" and "-l" parameter options. Refer to INFO:GCC for specific usage.

3. Shared function Library

Functions in a shared function library are loaded when an executable program is started. If a shared function library is installed properly, all programs can automatically load the latest functions in the library when they are rerun. There are many more features that can be implemented for Linux systems:
1, upgrade the function library but still allow the program to use the old version of the library.
2. When executing a particular program, you can overwrite a specific library or function specified in the library.
3. You can modify these library functions in the process of using the library function.

3.1. Some agreements
If you are writing a shared library that supports all the useful features, you must follow a series of conventions in the process of writing. You must understand the differences between the different names of the library, such as the difference between its "soname" and "real name" and how they interact. You also need to know where you should put these library functions in your filesystem and so on. Let's look at these issues in detail below.

3.1.1. Naming of shared libraries

Each shared function library has a special name, called "Soname". The soname name must be prefixed with "Lib", followed by the name of the library, then ". So", and finally the version number information. One exception, however, is that the very bottom C library functions are not named after Lib.
Each shared function library has a real name ("real name"), which is the file containing the real library function code. The real name has a major version number, and a release version number. The last release version number is optional and can not be used. The major version number and release number allow you to know exactly what version of the library function you are installing. Another name is the name of the library that the compiler needs to compile, which is a simple soname name and does not contain any version number information.

The key to managing shared libraries is to differentiate the names. When executable programs need to list the shared library functions they need in their own programs, it is only possible to use soname; in turn, when you want to create a new shared function library, you specify a specific file name that contains very detailed version information. When you install a new version of the library, you just have to copy the library files to some specific directory, run Ldconfig this practical. Ldconfig checks for the existing library file and then creates a soname symbol to link to the real library, while setting the/etc/ld.so.cache buffer file. We'll discuss this later.

Ldconfig does not set the name of the link, it is usually done during the installation process to complete the establishment of the link name, in general, this symbolic link simply points to the latest soname or the latest version of the function library file. It's a good idea to point this symbolic link to soname, because normally when you upgrade your library functions, you can automatically use the new version of the Library class.

Let's take a look at the example:/usr/lib/libreadline.so.3 is a fully complete soname,ldconfig can set a symbol to link to some other real library file, for example/usr/lib/ libreadline.so.3.0. There must also be a link name, such as/usr/lib/libreadline.so, which is a symbolic link pointing to/usr/lib/libreadline.so.3.

3.1.2. location of function library files in file system

Shared library files must be placed in a specific directory, so that the application can use these libraries correctly by setting the environment variables of the system. Most of the code development procedures follow the GNU standard, we can see the info help file to obtain the trust description, the location of info information is: info:standards#directory_variables. The GNU Standard recommends that all library files be placed in the/usr/local/lib directory, and that the command executable program is placed under the/usr/local/bin directory. These are some of the habit problems that can be changed.

The FileSystem Hierarchy Standard FHS (HTTP://WWW.PATHNAME.COM/FHS) specifies that most of the function library files in a distribution package should be installed in the/usr/lib directory. However, if some libraries are to be loaded when the system is started, they are placed in the/lib directory, and those libraries that are not part of the system itself are placed under/usr/local/lib.

There is no intrinsic conflict between the two paths above. The GNU standard is primarily for developers to develop the source code, while FHS's recommendations are for the path of the release. The specific location information can be seen in the/etc/ld.so.conf inside the configuration information.

3.2. How these libraries work

In GNU GLIBC-based systems, including all Linux systems, launching an elf-formatted binary executable automatically starts and runs a program loader. For Linux systems, the name of the loader is/lib/ld-linux.so.x (X is the version number). This loader starts and in turn will load all the other shared libraries that the program will use.

In what directories are you looking for a shared function library? These definitions are placed by default in the/etc/ld.so.conf file, and we can modify this file to include some of our own special path requirements. Most of the Redhat series/etc/ld.so.conf files do not include/usr/local/lib this directory, if not, we can modify the/etc/ld.so.conf, manually add this entry.

If you want to overwrite some of the functions in a library, replace them with your own functions, and keep the other functions in the library, you can add the libraries you want to replace (the files ending in. o) in/etc/ld.so.preload, and these preloading library functions will have priority loading rights.

It is obviously inefficient to search all the directories when the program starts, so the Linux system is actually using a high-speed buffering approach. Ldconfig reads the/etc/ld.so.conf related information by default, then sets the appropriate symbolic link and then writes a cache to the/etc/ld.so.cache file, and this/etc/ Ld.so.cache can be used effectively by other programs. This approach can greatly improve the speed of accessing the library. This requires that each time a new dynamically loaded library is added, run ldconfig to update the cache, and if you want to delete a function library, or if a library path has been modified, rerun ldconfig to update the cache. Typically, some package managers run Ldconfig when they install a new library of functions.

In addition, FreeBSD uses the cache file is not the same. The ELF cache for FreeBSD is/var/run/ld-elf.so.hints, while the a.out cache is/var/run/ld.so.hints. They are also updated by Ldconfig.

3.3. Environment variables

A variety of environmental variables control some of the key processes. For example, you can temporarily specify a different library of functions for one execution of your particular program. In Linux systems, the usual variable ld_library_path can be used to specify the function library to find the path, and this path is usually found before looking for a standard path. This is useful, especially when debugging a new library of functions, or when using a nonstandard library of functions in special situations. The environment variable ld_preload lists the library files that need to be loaded first in all shared function libraries, similar in functionality to/etc/ld.so.preload. These are all/lib/ld-linux.so this loader to achieve. It is worth mentioning that Ld_library_path can function normally under most unix-linke systems, but not all systems can be used, such as the HP-UX system, which uses the Shlib_path variable, The LIBPATH variable is used under AIX.

Ld_library_path in the development and debugging process is often used extensively, but should not be an ordinary user in the installation process by the installation program modification, we can refer to http://www.visi.com/~barr/ldpath.html, Here is a document that specifically explains why you should not use the Ld_library_path variable.

In fact, there are more environment variables that affect the process of program transfer, and their names usually begin with Ld_ or rtld_. Most of the documents used in these environment variables are incomplete, often confusing, and if you want to really figure out how to use them, it's best to read Loader's source code (which is part of GCC).

Allowing the user to control the dynamic Link function library will involve setuid/setgid this function if special functions are required. As a result, the GNU loader typically restricts or ignores the use of setuid and setgid by users with these variables. If loader determines whether the program uses setuid or setgid by judging the relevant environment variables of the program, if the UID and euid are different, or GID and egid, then loader assumes that the program has used setuid or setgid, Then the large limiter controls the permissions of this old link. If you read the GNU glibc Library function source code, you can see this clearly. In particular, we can look at the two files of ELF/RTLD.C and sysdeps/generic/dl-sysdep.c. This means that if you make the UID and GID equal to Euid and Egid, and then call a program, these variables can be fully effective.

3.4. Create a shared function library

Now let's learn how to create a shared function library. Actually creating a shared library is very easy. First create the object file, which will be added to the shared function library via the gcc–fpic parameter command. Pic means "location Independent code" (Position independent Codes). The following is a standard format:

Gcc-shared-wl,-soname,your_soname-o library_name file_list library_list

Here is an example that creates two object files (A.O and B.O) and then creates a shared library of functions that contains A.O and B.O. The "-G" and "-wall" parameters are not required in the example.

Gcc-fpic-g-c-wall A.C

Gcc-fpic-g-c-wall B.C

Gcc-shared-wl,-soname,liblusterstuff.so.1-o liblusterstuff.so.1.0.1 A.O B.O-LC

Here are some things to keep in mind:

Do not use-fomit-frame-pointer this compilation parameter unless you have to. Although the library of functions obtained using this parameter can still be used, this makes the debugger almost useless and cannot track debugging.

Use-fpic to generate code instead of-fpic.

In some cases, using GCC to generate an object file requires the option parameter "-wl,-export-dynamic".

Typically, the symbol table of a dynamic function library contains the symbols for these dynamic objects. This option adds all symbols to the dynamic symbol table when you create an elf-formatted file. You can refer to LD's help for a more detailed explanation.

3.5. Installing and using the shared functions Library

Once you have defined a shared function library, you will need to install it. The simple way to do this is to copy your library file to the specified standard directory (for example,/usr/lib) and run Ldconfig.

If you do not have permission to do this, for example you cannot modify the/usr/lib directory, then you will have to modify your environment variables to implement these library use. First, you need to create these shared function libraries, and then set up some symbolic links that must be signed, especially from Soname to the real library file, and the simple way is to run Ldconfig:

Ldconfig-n directory_with_shared_libraries
Then you can set your Ld_library_path this environment variable, which is a comma-delimited collection of paths that can be used to indicate the search path of a shared function library. For example, using bash, you can start a program My_program:

Ld_library_path= $LD _library_path My_program

If you need an overloaded part of the function, you need to create an object file that contains the function you want to overload, and then set the LD_PRELOAD environment variable.

Usually you can easily upgrade your library, and if an API changes, the program that created the library will change soname. However, if a function has upgraded a function library and maintained the original soname, you can forcibly copy the old version of the library to a location, then rename the file (for example, use the original name, followed by the. orig suffix), and then create a small "wrapper" Script to set this library function and related things. For example, the following example:

#!/bin/sh export Ld_library_path=/usr/local/my_lib, $LD _library_path

Exec/usr/bin/my_program.orig $*

We can see the shared function library used by a program by running LDD. For example, you can see the function library used by the LS utility:

Ldd/bin/ls

libtermcap.so.2 =/lib/libtermcap.so.2 (0x4001c000)

libc.so.6 =/lib/libc.so.6 (0x40020000)

/lib/ld-linux.so.2 =/lib/ld-linux.so.2 (0x40000000)
Usually I can see a list of soname, including the path. In all cases, you can see at least two libraries:

· /LIB/LD-LINUX.SO.N (N is 1 or greater, generally at least 2). This is the library that is used to load all the other shared libraries.

· LIBC.SO.N (N should be greater than or equal to 6). This is the C-language function library.

It is worth mentioning that you should not run the LDD command on a program that you do not trust. In LDD's manual it is clear that LDD is set by setting certain special environment variables (for example, for Elf objects, setting ld_trace_loaded_objects) and then running the program. This makes it possible for a place program to cause LDD to execute some unexpected code, creating unsafe pitfalls.

3.6. Incompatible Library of functions

If a new version of the library is incompatible with older versions of the binary library, the soname needs to be changed. For the C language, there are 4 basic reasons why they are difficult to be compatible with in binary code:

The wording of a function changes so that it may not match the initial definition.

· The data item for the output has changed.

· Some of the output functions have been removed.

· The interface for some output functions has changed.
If you can avoid these places, you can keep your library compatible with binary code, or, you can make your program's application binary interface (abi:application binary Interface) compatible.

4. Dynamically loaded library of functions dynamically Loaded (DL) Libraries

Dynamically loaded library dynamically loaded (DL) libraries is a library of functions that can be loaded at any time during the program's run. They are particularly well suited for loading modules and plugin extension modules in functions, because they can be loaded dynamically when a program needs a plugin module. For example, the pluggable authentication Modules (PAM) system is a dynamic load function library that enables administrators to configure and reconfigure authentication information.

There is no special difference in format between DL libraries and other libraries under Linux, as we mentioned earlier, when they were created in the standard object format. The main difference is that these libraries are not loaded when the program is linked or started, but rather through an API that opens a library of functions, looks for symbol tables, handles errors, and closes libraries. Typically, this header file needs to be included in the C language environment.
The functions used in Linux are the Dlpoen () APIs, as in Solaris. Of course not all platforms use the same interface, such as HP-UX using the shl_load () mechanism, while the Windows platform uses a different other calling interface. If your goal is to make your code highly portable, you should use some wrapping libraries, such that the wrapping library hides the interface differences between different platforms. One approach is to use the support for dynamic loading modules in the GLIBC library, which uses some of the potentially dynamic load function library interfaces to make them boast platform usage. Refer to http://developer.gnome.org/doc/API/glib/glib-dynamic-loading-of-modules.html for details. Another method is to use the Libltdl, which is part of the GNU Libtool, and can be further referenced by the CORBA related data.

4.1. Dlopen ()
The Dlopen function opens a library of functions and prepares for subsequent use. The C-language prototype is:

void * Dlopen (const char *filename, int flag);

If the file name filename is prefaced with "/", that is, the absolute path is used, then DLOPNE will use it directly instead of looking for some environment variables or directories of the system's library of functions. otherwise Dlopen () will look for the function library file in the following order:
1. Environment variable ld_library the specified path.

2. List of function libraries in/etc/ld.so.cache.

3./lib directory, then/usr/lib. But some very old a.out loader are in the opposite order, that is, to check/usr/lib first, then/lib.
In the Dlopen () function, the value of the parameter flag must be Rtld_lazy or rtld_now,rtld_lazy means resolve undefined symbols as code from the dynamic library is Executed, while rtld_now means resolve all undefined symbols before dlopen () returns and fail if this cannot is done '.
If there are several libraries that have dependencies between them, such as x-dependent Y, then you need to load the dependent functions first. For example, load y first and then load X.

The return value of the Dlopen () function is a handle, and the subsequent function uses the handle to do further work. If Open fails Dlopen () returns a null. If a function library is opened more than once, it returns the same handle.
If a function library has an output function whose name is _init, then _init will be executed before the function returns Dlopen (). We can use this function to do some initialization work in my library. We will continue to discuss the issue later.
4.2. Dlerror ()

By calling the Dlerror () function, we can get an error message for the last call to Dlopen (), Dlsym (), or dlclose ().
4.3. Dlsym ()

If you load a DL library without using it is of course not possible, the main function of using a DL library is Dlsym (), which looks for a given symbol in an open library of functions. This function is defined as follows:

void * Dlsym (void *handle, char *symbol);

The parameter handle in the function is the handle returned by the Dlopen open, and symbol is a string that ends with nil. Returns null if the Dlsym () function does not find the symbol to look for. If you know that the value of a symbol cannot be null or 0, then it is good that you can determine if the symbol you are looking for exists in terms of the return result, but if the value of a symbol is NULL, then this judgment is problematic. The standard method of judging is to call Dlerror (), clear a previous error, and then call Dlsym () to access a symbol and then call Dlerror () to determine if an error has occurred. A typical process is as follows:

4.4. Dlclose ()

The inverse of the Dlopen () function is the Dlclose () function, and the Dlclose () function closes a DL function library forcefully. The DL function Library maintains a resource utilization counter, and when the dlclose is called, the counter is counted minus one, and if the counter is 0, it is actually released. When really released, if the function library has _fini () This function, then automatically call _fini () This function, do some necessary processing. Dlclose () returns 0 for success, and other non-0 values indicate an error.

4.5. DL Library Example

Here is an example. In the example, enter the math library and print the cosine function value of 2.0. The example checks for errors every time. Should be a good example:

If the program is named FOO.C, compile it with the following command:

Gcc-o Foo FOO.C–LDL

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.