[Linux] Dynamic and static libraries

[Linux] Dynamic and static libraries

Jianyijianku

In Linux systems, the C Standard Library and other commonly used libraries are called C libraries and are usually stored in the /usr/libor /usr/lib64directory:

image-20230907132423757

In Linux systems, /usr/includemany header files are stored in the directory:

image-20230907132557509

  • 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.
  1. 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; 
}
  1. Compile source files into target files

gcc -c 源文件名Compile source files into target files using :

image-20230907162247874

  1. Packaged into a static library

Use ar -rc lib库名.a 目标文件to package the target file into a static library:

image-20230907162355901

  1. 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:

image-20230907162516768

  1. Package the library into a compressed package

Use tar -czf 目标压缩包名 源文件to package the library into a compressed package:

image-20230907162735301

Simulate the use of static libraries

  1. 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

image-20230907164341754

  1. 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;
}
  1. Compile the source file main.c into an executable program:

image-20230907165017051

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 库名)
  • 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.

  1. Compile source files

When packaging a dynamic library, you need to gcc -fPIC -c 源文件名compile the source file into a target file:

image-20230907173438259

  1. Package target files into dynamic libraries

Use gcc -shared -o lib库名.so 目标文件to package the target file into a dynamic library:

image-20230907173847412

  1. 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:

image-20230907174146799

  1. Package the library into a compressed package

Use tar -czf 目标压缩包名 源文件to package the library into a compressed package:

image-20230907174229960

Simulate the use of static libraries

  1. 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

image-20230907184457085

  1. 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;
}
  1. 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:

image-20230907184623458

  1. 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:

image-20230907185214813

Methods to solve the problem that the third-party dynamic library cannot be found by the OS:

  1. 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.
  2. Establish a soft link to the dynamic library under the system path: use to sudo ln -s 动态库路径 /lib64/lib库名.soadd the soft link to the dynamic library to the system path
  3. Modify the configuration file: /etc/ld.so.conf.d/Create .confa file with the suffix under the path, write the path of the static library to the file, and then use to sudo ldconfigmake 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:

image-20230908133542761

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:

image-20230908133642887

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:

image-20230908133705099

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 -fPICto 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 -staticthe 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.

Guess you like

Origin blog.csdn.net/csdn_myhome/article/details/132758600
Recommended