Dynamic libraries with different version numbers may be incompatible, assuming that the program specifies that the dynamic library is a low version number at compile time. Execution is a high version number that may result in an inability to execute.
The name of the dynamic library on Linux is in LIBXXX.SO.A.B.C format. A represents the large version number. b stands for the minor version number, and C for the smaller version number. We use the Linux-brought CP program as an example to view its dependent dynamic libraries through LDD
$ ldd /bin/cp linux-vdso.so.1 => (0x00007ffff59df000)libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fb3357e0000)librt.so.1 => /lib64/librt.so.1 (0x00007fb3355d7000)libacl.so.1 => /lib64/libacl.so.1 (0x00007fb3353cf000)libattr.so.1 => /lib64/libattr.so.1 (0x00007fb3351ca000)libc.so.6 => /lib64/libc.so.6 (0x00007fb334e35000)libdl.so.2 => /lib64/libdl.so.2 (0x00007fb334c31000)/lib64/ld-linux-x86-64.so.2 (0x00007fb335a0d000)libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fb334a14000)
The left side is dependent on the dynamic library name, the right is the link to the file, and then see the libacl.so related dynamic library
$ ll /lib64/libacl.so* lrwxrwxrwx. 1 root root 15 1月 7 2015 /lib64/libacl.so.1 -> libacl.so.1.1.0-rwxr-xr-x. 1 root root 31280 12月 8 2011 /lib64/libacl.so.1.1.0
We find that libacl.so.1 is actually a soft link, and the file it points to is libacl.so.1.1.0, which is named in accordance with the descriptive narrative above. It's not named this way, for example.
$ ll /lib64/libc.so* lrwxrwxrwx 1 root root 12 8月 12 14:18 /lib64/libc.so.6 -> libc-2.12.so
In any case, simply create and use a dynamic library in a prescribed manner. There will be no problem.
And we tend to compile the program on machine A. Executing the program on machine B, compiling and executing the environment is actually slightly different. The following are some of the problems in the process of generating and using dynamic libraries
Compilation of dynamic libraries
Let's take a simple procedure as a sample
// filename:hello.c#include <stdio.h>void hello(const char* name){ printf("hello %s!\n", name);}// filename:hello.hvoid hello(const char* name);
Compile with a command such as the following
gcc hello.c -fPIC -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.1
Note that -Wl,soname
there is no space in the middle, and the -Wl
option tells the compiler to pass the following parameters to the linker,
-soname
The Soname (simple share name) for the dynamic library is specified. Short for shared object name)
Now that we have generated libhello.so.0.0.1, when we execute ldconfig -n .
the command, the current folder will have one more soft connection
$ ll libhello.so.0 lrwxrwxrwx 1 handy handy 17 8月 17 14:18 libhello.so.0 -> libhello.so.0.0.1
How this soft link is generated is not the first part of the libhello.so.0.0.1 name, but is generated based on the-soname specified at libhello.so.0.0.1 compile time. That is to say, when we compile the dynamic library, the name specified by-soname has been recorded in the binary data of the dynamic library. Regardless of whether the program is named in LIBXXX.SO.A.B.C format, but almost all of the dynamic libraries on Linux have been specified at compile time-soname, we can view soname through the Readelf tool, for example, the two dynamic libraries listed at the beginning of the article
$ readelf -d /lib64/libacl.so.1.1.0 Dynamic section at offset 0x6de8 contains 24 entries:Tag Type Name/Value0x0000000000000001 (NEEDED) Shared library: [libattr.so.1]0x0000000000000001 (NEEDED) Shared library: [libc.so.6]0x000000000000000e (SONAME) Library soname: [libacl.so.1]
Part of this is omitted to see the last line Soname as libacl.so.1. That's why/lib64 has a soft connection.
Look at the libc-2.12.so file again, and the file doesn't use the naming method we're talking about.
$ readelf -d /lib64/libc-2.12.so Dynamic section at offset 0x18db40 contains 27 entries:Tag Type Name/Value0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]0x000000000000000e (SONAME) Library soname: [libc.so.6]
The same can see the last line Soname as libc.so.6. Even though the dynamic library is not named by the version number, there is still a soft chain pointing to the dynamic library, and the name of the soft chain is the name of the soname designation.
So the key is this soname, which is equivalent to a middle person. When our dynamic library simply upgrades a minor version number, we can make it soname the same. The executable program only soname the specified dynamic library, so that the executable program that relies on the dynamic library can use the features of the new dynamic library without having to compile again
Compilation of executable programs
Or with the Hello Dynamic library as an example, we write a simple program
// filename:main.c#include "hello.h"int main(){ hello("handy"); return 0;}
Now folders are for example the following structure
├── hello.c├── hello.h├── libhello.so.0 -> libhello.so.0.0.1├── libhello.so.0.0.1└── main.c
libhello.so.0.0.1 is a dynamic library that we compile and build, and libhello.so.0 is a link generated through Ldconfig. Use the following command for example to compile MAIN.C
$ gcc main.c -L. -lhello -o main /usr/bin/ld: cannot find -lhello
Error cannot find the Hello Dynamic library, under Linux, at compile time to specify-lhello, the linker will go to find libhello.so this file. The current folder does not have this file, so error.
Build such a soft chain. folder structure such as the following
├── hello.c├── hello.h├── libhello.so -> libhello.so.0.0.1├── libhello.so.0 -> libhello.so.0.0.1├── libhello.so.0.0.1└── main.c
Let the libhello.so link point to the actual dynamic library file libhello.so.0.0.1. Then compile the main program
gcc main.c -L. -lhello -o main
The executable file is then generated.
Through the above test we found that when compiling the executable program. The linker will look for a file that it relies on to libxxx.so. Therefore, the existence of libxxx.so must be ensured.
Use LDD to view its dependent dynamic libraries
$ ldd main linux-vdso.so.1 => (0x00007fffe23f2000) libhello.so.0 => not found libc.so.6 => /lib64/libc.so.6 (0x00007fb6cd084000) /lib64/ld-linux-x86-64.so.2 (0x00007fb6cd427000)
We found that the main program relies on the dynamic library name libhello.so.0. Neither Libhello.so nor libhello.so.0.0.1. In fact, the process of generating the main program has several steps, such as the following
-L. -lhello
the linker finds the libhello.so file in the current folder by compiling commands
- Reads the actual file that the libhello.so link points to. This is libhello.so.0.0.1.
- Read the soname in libhello.so.0.0.1, this is libhello.so.0.
- Log the libhello.so.0 into the binary data of the main program
That is, libhello.so.0 is already stored in the main program's binary data, regardless of where the program, through LDD to see it depends on the dynamic library is libhello.so.0
And why here LDD view main shows that libhello.so.0 is not found. Since LDD is looking for a file from the path specified by the environment variable $ld_library_path, we specify the environment variable to perform the following
$ export LD_LIBRARY_PATH=. && ldd main linux-vdso.so.1 => (0x00007fff7bb63000) libhello.so.0 => ./libhello.so.0 (0x00007f2a3fd39000) libc.so.6 => /lib64/libc.so.6 (0x00007f2a3f997000) /lib64/ld-linux-x86-64.so.2 (0x00007f2a3ff3b000)
Execution of executable programs
Now test folder results such as the following
├── hello.c├── hello.h├── libhello.so -> libhello.so.0.0.1├── libhello.so.0 -> libhello.so.0.0.1├── libhello.so.0.0.1├── main└── main.c
Here we mix the build environment with the execution environment. It just doesn't matter. We just need to know the principle. You can make it clear.
We have already viewed the dynamic library that the main program relies on by LDD, and have specified the Ld_library_path variable, and can now execute directly
$ ./main hello Handy!
It looks very smooth. So suppose we want to deploy the execution environment, how to deploy it.
Obviously, the source code is not required, we only need dynamic libraries and executable programs. Create a new execution folder here. and copy the relevant files, folder structure such as the following
├── libhello.so.0.0.1└── main
At this point, main will find
$ ./main ./main: error while loading shared libraries: libhello.so.0: cannot open shared object file: No such file or directory
Error said libhello.so.0 file can not be found, that is, the program execution needs to find the dynamic library file name is actually the dynamic library compile time specified soname, which is also consistent with our LDD view.
By ldconfig -n .
establishing a link, such as the following
├── libhello.so.0 -> libhello.so.0.0.1├── libhello.so.0.0.1└── main
Re-execute the program, and the results will match the expectations.
From the above test, the program does not need to know libxxx.so when executing, but the soname of the dynamic library that the program itself records. Therefore, the execution environment of the main program requires only the above three files to
Dynamic library Version number update
Suppose a dynamic library needs to make a small change, such as the following
// filename:hello.c#include <stdio.h>void hello(const char* name){ printf("hello %s, welcom to our world!\n", name);}
Because the modifications are small, we still specify the same soname when we compile the dynamic library
gcc hello.c -fPIC -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.2
Copy the new dynamic library to the execution folder. The folder structure is now executed such as the following
├── libhello.so.0 -> libhello.so.0.0.1├── libhello.so.0.0.1├── libhello.so.0.0.2└── main
A dynamic library with two version numbers under the folder is now available. But libhello.so.0 points to the strongholds version, and ldconfig -n .
after execution we find that the link points to the new version number, such as the following
├── libhello.so.0 -> libhello.so.0.0.2├── libhello.so.0.0.1├── libhello.so.0.0.2└── main
Re-execute the program
$ ./main hello Handy, welcom to our world!
The new dynamic library, wonderful, was used without compiling it again.
Same. If there is a big change in our dynamic library. A new soname is specified when compiling the dynamic library. For example, the following
gcc hello.c -fPIC -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0.0
Copy the dynamic library file to the execution folder. and execute ldconfig -n .
, folder structure such as the following
├── libhello.so.0 -> libhello.so.0.0.2├── libhello.so.0.0.1├── libhello.so.0.0.2├── libhello.so.1 -> libhello.so.1.0.0├── libhello.so.1.0.0└── main
This time found that the new link libhello.so.1 generated, and the main program is still using the libhello.so.0, so the new version of the dynamic library can not use the functionality, need to compile again.
At last
In the actual production environment, the compilation and execution of the program is often separate, but only to understand the principles of this series of processes, it is not afraid to be the version number of the dynamic library to stun. In simple terms, do it as follows
- Specified when compiling a dynamic library
-Wl,-soname,libxxx.so.a
. Set Soname to LIBXXX.SO.A, generate the actual dynamic library file LIBXXX.SO.A.B.C,
- Libxx.so is guaranteed to exist when compiling executable programs. The hypothesis is a soft chain. Must point to the actual dynamic library file LIBXXX.SO.A.B.C
- Ensure that the LIBXXX.SO.A.B.C file exists when executing the executable file, Ldconfig generated LIBXXX.SO.A link to LIBXXX.SO.A.B.C
- environment variable setting ld_library_path, executing executable program
Eof
Linux program compiling link dynamic Library version number problem