[Linux] Dynamic and static libraries
Article directory
Jianyijianku
In Linux systems, the C Standard Library and other commonly used libraries are called C libraries and are usually stored in the /usr/lib
or /usr/lib64
directory:
In Linux systems, /usr/include
many header files are stored in the directory:
- The Linux system is pre-installed with C/C++ header files and library files. The header files provide descriptions of the methods, and the library files provide the implementation of the methods. The header files and library files have a corresponding relationship and need to be used in combination.
- In the process of compiling a program to form an executable program, header files are introduced during preprocessing and library files are linked during linking.
- When installing the development environment under visual studio, not only the compiler software is installed, but also the header files and library files corresponding to the language are installed.
- The compiler will automatically search for relevant content in the header file based on the user's input and implement the syntax prompt function.
- The compiler will automatically and continuously compile based on the user's input to implement the function of reporting syntax errors.
The reason why the library exists
The programming language adds commonly used functions to the library so that users can directly use these functions and improve development efficiency. For example printf
, users do not need to write a function for printing data every time they want to print data.
Writing a library
Simulate writing static libraries
Before writing the library, please explain:
- Libraries are divided into dynamic libraries and static libraries
- Naming rules for static libraries under Linux:
lib库名.a
- Naming rules for dynamic libraries under Linux:
lib库名.so
- Cloud services generally do not have built-in static libraries.
- Writing header files and source files
Write the header file myadd.h and its corresponding source file myadd.c and the header file mysub.h and its corresponding source file mysub.c. The specific codes in each file are as follows:
//myadd.h
#pragma once
int my_add(int x, int y);
//myadd.c
#include "myadd.h"
int my_add(int x, int y)//一个简单的加法函数
{
return x + y;
}
//mysub.h
#pragma once
int my_sub(int x, int y);
//mysub.c
#include "mysub.h"
int my_sub(int x, int y)//一个简单的减法函数
{
return x - y;
}
- Compile source files into target files
gcc -c 源文件名
Compile source files into target files using :
- Packaged into a static library
Use ar -rc lib库名.a 目标文件
to package the target file into a static library:
- Simulation library file directory structure
Create the include directory and move the header files into this directory, and create the lib directory and move the static libraries into this directory:
- Package the library into a compressed package
Use tar -czf 目标压缩包名 源文件
to package the library into a compressed package:
Simulate the use of static libraries
- Copy the static library compressed package packaged in the previous operation to a certain directory and decompress it to simulate the download process of the library
- Create the source file main.c in the current directory and write the code to call the static library. The specific code is implemented as follows:
#include <stdio.h>
#include "myadd.h"
#include "mysub.h"
int main()
{
int x = 20;
int y = 10;
printf("%d + %d = %d\n", x, y, my_add(x, y));
printf("%d - %d = %d\n", x, y, my_sub(x, y));
return 0;
}
- Compile the source file main.c into an executable program:
Since the third-party header file is not in the compiled directory, -I 路径
an option is required to specify the header file path. Since the third-party library compiler will not find and use it by itself, -L 路径
the library file path name and -l 库名
the library name need to be specified.
Summarize the use of third-party libraries under Linux systems:
- You need to specify the header file path and the path and name of the library file.
- If the header files and library files are not installed to the default path searched by the compiler, the user must specify the corresponding options:
- Header file path (
-I 路径
) - Library file path (
-L 路径
) - Library name (
-l 库名
)
- Header file path (
- The essence of installing header files and library files is to copy the files to the system default path.
- After the header files and library files are installed, you need to specify the library name option when compiling.
Simulate writing dynamic libraries
When simulating writing a dynamic library, the header file myadd.h and its corresponding source file myadd.c and the header file mysub.h and its corresponding source file mysub.c used in the previous article to package the static library are used.
- Compile source files
When packaging a dynamic library, you need to gcc -fPIC -c 源文件名
compile the source file into a target file:
- Package target files into dynamic libraries
Use gcc -shared -o lib库名.so 目标文件
to package the target file into a dynamic library:
- Simulation library file directory structure
Create the include directory and move the header files into this directory, and create the lib directory and move the static libraries into this directory:
- Package the library into a compressed package
Use tar -czf 目标压缩包名 源文件
to package the library into a compressed package:
Simulate the use of static libraries
- Copy the dynamic library compressed package packaged in the previous operation to a certain directory and decompress it to simulate the download process of the library
- Create the source file main.c in the current directory and write the code to call the static library. The specific code is implemented as follows:
#include <stdio.h>
#include "myadd.h"
#include "mysub.h"
int main()
{
int x = 20;
int y = 10;
printf("%d + %d = %d\n", x, y, my_add(x, y));
printf("%d - %d = %d\n", x, y, my_sub(x, y));
return 0;
}
- Compile the source file main.c into an executable program:
After specifying the path of the dynamic library header file, the path of the library file and the library name, the compiler can compile successfully. Since it is a dynamic library, when the program is running, the OS needs to link to the dynamic library according to the dynamic library address in the program to run successfully, but the OS The dynamic library cannot be found, resulting in the following situation:
- Use the method of importing environment variables to make the program run (temporary solution)
By export LD_LIBRARY_PATH=LD_LIBRARAY_PATH:动态库所在目录路径
importing the dynamic library path into the environment variable, the OS will find the dynamic library from the path in the environment variable when running the program and run it successfully:
Methods to solve the problem that the third-party dynamic library cannot be found by the OS:
- Import environment variables: Use
export LD_LIBRARY_PATH=LD_LIBRARAY_PATH:动态库所在目录路径
the dynamic library path to import environment variables. The environment variables will be reloaded when the shell is reopened, so it is a temporary solution. - Establish a soft link to the dynamic library under the system path: use to
sudo ln -s 动态库路径 /lib64/lib库名.so
add the soft link to the dynamic library to the system path - Modify the configuration file:
/etc/ld.so.conf.d/
Create.conf
a file with the suffix under the path, write the path of the static library to the file, and then use tosudo ldconfig
make the configuration file take effect.
Library loading principle
Static library loading principle
The loading process of the dynamic library is to directly copy the implementation in the static library to the executable program during the linking process to form the executable program. Therefore, static libraries occupy a lot of resources (disk, memory, network resources).
Dynamic library loading principle
First of all, when using a dynamic library to generate an executable program, during the linking process, only the external symbols representing methods in the library will be replaced with corresponding addresses in the executable program. Since there is no specific implementation in the executable program, it is difficult to run Up, the operating system does a series of work. After the program is loaded into the memory to form a process, the operating system maintains the process control block, process address space and page table for it:
After the process runs into the method in the dynamic library, the operating system will look for the mapping in the page table and find that what is mapped to the memory is only a corresponding address rather than a specific method implementation. Therefore, the operating system looks for this dynamic library and converts the dynamic library to the dynamic library according to a certain strategy. The library is loaded into memory, and then the operating system maps the dynamic library loaded into memory to the shared area between the stack area and the heap area in the process address space:
Then, every time the process executes a method in the library, it only needs to jump to the shared area in the process address space to complete the execution of the program:
In addition, after the library is loaded into the memory, when the subsequent running process needs to execute the library method, there is no need to load the library in the memory. Instead, the shared area mapping is directly created, and then the methods in the library are used.
Addressing strategies for libraries in executable programs
Addressing strategy of static libraries in executable programs
When an executable program is formed, there will be a logical address in the executable program. If a static library is used, the methods of the static library in the executable program will also be addressed and a logical address will be obtained. When the program becomes a process and runs, only Just jump based on the logical address.
Addressing strategy of dynamic libraries in executable programs
When an executable program is formed, there will be a logical address in the executable program. If a dynamic library is used, the methods of the dynamic library in the executable program will also be addressed, but this address is the starting address of the method in the library. The starting offset. When making a dynamic library to obtain the target file, use gcc to add it -fPIC
to obtain this address offset, which is called an address-independent code. When the actual process is running, the process only needs to wait for the method in the library. It is loaded into memory and mapped to the shared area, and then uses the shared area mapping plus the offset address to complete the operation.
Explain:
- When the gcc/g++ compiler compiles an executable program, it uses dynamic libraries by default.
- When the gcc/g++ compiler compiles an executable program, using
-static
the option will use a static library. - When the gcc/g++ compiler compiles an executable program, some dynamic libraries do not exist, and a mixed use of dynamic libraries is used.