[Linux] dynamic library and static library

Table of contents

I. Introduction

2. Static library and dynamic library

3. Generate a static library

1. Generation principle

2. The complete process

3. Summary

Fourth, generate a dynamic library

1. Environment variables

2. Establish a soft link

3. Configuration file

Five, dynamic library loading

1. The process of dynamic library loading

2. Understanding of dynamic library address

3. Supplementary content


I. Introduction

 Regarding a small part of the pre-content of dynamic libraries and static libraries, I have explained in detail in the article "Compiler-gcc && Function Library" .

 In fact, the system has pre-installed C/C++ header files and library files. The header file provides a description of the method, and the library function provides the implementation of the method. The header and the library are to be used together. The header file is introduced in the preprocessing stage, and the essence of the link is the link library.

 So when we install the development environment, we are actually installing the libraries and header files for the corresponding language. When using the compiler, there will be an automatic reminder of the syntax, which needs to include the header file first. The essence of syntax reminder is that the compiler will automatically search the content entered by the user in the included header files, and the automatic reminder function is realized by relying on header files.

 When writing code, the reason why the environment knows where there are grammatical errors in the code and where there are problems defining variables is because the compiler works in command line mode and other automatic modes. When the user writes code, it will continuously Preprocessing and compiling operations help users to perform grammar checks continuously.

 The purpose of the library is to improve development efficiency.

2. Static library and dynamic library

  1. Static library (.a): The program links the code of the library into the executable file when compiling and linking. The static library is no longer needed when the program is running.
  2. Dynamic library (.so): The code of the dynamic library is only linked when the program is running, and multiple programs share the code of the library.
  3. An executable file linked with a dynamic library only contains a table of the entry addresses of the functions it uses, rather than the entire machine code of the object file where the external function is located.
  4. Before the executable file starts running, the machine code of the external function is copied from the dynamic library on the disk to the memory by the operating system. This process is called dynamic linking.
  5. Dynamic libraries can be shared among multiple programs, so dynamic linking makes executable files smaller and saves disk space. The operating system uses a virtual memory mechanism to allow a dynamic library in physical memory to be shared by all processes that use the library, saving memory and disk space.
  6. Generally, cloud servers only have dynamic libraries by default, and there are no static libraries. Static libraries need to be installed independently.

3. Generate a static library

1. Generation principle

Here is a simple addition and subtraction program:

//myadd.h
#pragma once
int myadd(int d1, int d2);

//myadd.c
#include "myadd.h"
int myadd(int d1, int d2)
{
    return d1 + d2;
}

//mysub.h
#pragma once
int mysub(int d1, int d2);

//mysub.c
#include "mysub.h"
int mysub(int d1, int d2)
{
    return d1 - d2;
}

After the above program is written, you can directly package the source code for other programs to use:

 Compile and run:

 The result is as expected.


 If we want others to call some functions of our program, but do not want to hand over the source code to others, we can preprocess, compile and assemble our program to generate an .o file, and then relocate the target binary file . Give it to someone else to use.

Now separate the source code for implementing the function and the program for using the function into the mylib and otherPerson directories respectively:

 Use the command gcc -c [source file] to generate the .o file and put it in the otherPerson directory:

 After entering the otherPerson directory, first use the command gcc -c to generate the .o file of the main.c file , then link it with other .o files, and finally generate an executable file:

 The end result is as expected.


In order to facilitate the transmission of .o files, we usually package these files. Package and generate static library instructions:

ar -rc [lib文件名.a] [*.o]

 After copying both the *.a file and the *.h file to otherPerson, compile main.c to generate an executable program:

 The error reported above is because when you have a library, you must let the compiler find the header file and library file if you want to import the library into the project. Since gcc and g++ only know C language and C++ libraries, the libraries we introduced ourselves belong to third-party libraries, and the compiler doesn't know them, so of course they can't find them.

 Therefore, you must specify which library you need to link yourself:

gcc -o [可执行程序] [被编译文件] -L[库所处路径] -l[库名]

 The result is as expected.

2. The complete process

 With the above knowledge, we already know how static libraries are packaged and handed over to others for use. But in fact, the real steps of transferring and using the static library are different from those demonstrated above. The specific process is as follows:

 After the static library is formed, create an include directory and a lib directory, and put  the .h file and the .a  file respectively:

 Next, in order for others to use your own static library, you can package and upload these two directories for others to download and use:

 Use the static library directive:

gcc -o [可执行文件] [源代码文件] -I[头文件路径] -L[库文件路径] -l[库文件名称]

 Compile and run the observation results combined with the static library:

 The result is as expected.

 If you don't want to specify such a long list of paths during compilation, you can also directly copy the corresponding header files and library files to the default search paths of gcc and g++:

 After that, there is no need to specify the path of the header file and library, just specify the name of the third-party library to compile and use normally.

3. Summary

When generating and using a third-party library by yourself, two conditions need to be met:

  1. Need to specify header files and library files
  2. If the library is not installed in the default search path of the system gcc and g++, the user must specify the corresponding options to inform the compiler: where is the header file, where is the library file, and what is the name of the library file.
  3. Copy the downloaded library and header files to the default path of the system, which is called the installation of the library in the operating system. For any software, the essence of installation and uninstallation is to copy to a system-specific path, or delete it from a specific path.
  4. If the library we installed is a third-party (the first party is the language, the second party is the operating system call interface), when using it, you need to use -l to specify the name of the corresponding library.
  5. Whether we are directly downloading the library from the network, or the source code (compilation method). A make install installation command will be provided, and what this command does is to install it into the system. Most of the instructions, libraries, etc. we install require sudo privilege escalation.

Fourth, generate a dynamic library

shared: 表示生成共享库格式
fPIC:产生位置无关码(position independent code)
库名规则:libxxx.so

 When generating the dynamic library .o file, you need to add the -fPIC command option to the command gcc to generate a position-independent code:

 Next, the same as the static library, you also need to package the .o file for uploading. The difference is that the dynamic library is packaged using gcc instructions:

gcc -shared -o [lib库名.so] [*.o]

  After the dynamic library is formed, create an include directory and a lib directory, and place  the .h file and the .a  file respectively:

 Next, in order for others to use your own dynamic library, you can package and upload these two directories for others to download and use:

 Observation results after compiling with a dynamic library:

 It was found that the program reported an error, indicating that the shared object file could not be opened.

 This is because we use the -l  and -L options to specify the path, which is explained to the compiler, not to the OS. When the program is running, because the .so is not in the default path of the system, the OS still cannot find it.

 Note that this is distinguished from static libraries. Static libraries can run this way because the linking principle of static libraries is to directly copy the binary code used by the user into the target executable program, but dynamic libraries will not.

 The OS finds the dynamic library in the following ways:

  1. Set the environment variable: LD_LIBRARY_PATH.
  2. Create a soft link under the path specified by the system to point to the corresponding library.
  3. configuration file.

1. Environment variables

  Use the echo command to view the environment variable LD_LIBRARY_PATH :

 Just use the export command to add the path of the library to the environment variable:

 At this point, the program can be executed normally, and the result is as expected.

 Because the environment variables will be reset when we log out of the terminal and log in again, we need to reset the environment variables when we log in next time, otherwise it will not work properly.

2. Establish a soft link

 Because the default search path for libraries is /usr/lib64 and /lib64 . So we can directly select a path and create a soft link to the corresponding library under this path. Here we take /lib64 as an example:

Compile and run, the result is as expected.

Because the soft link is a normal file, it is always saved on the disk, so when we log out and log in again, the program can still run normally. 

3. Configuration file

The path where the relevant configuration files are located: /etc/ld.so.conf.d :

These configuration files store the path where the library is located.

 Now we touch a configuration file in this directory and enter the path of the required library in the configuration file:

 After changing the configuration file, you need to make the configuration file take effect. Take the command:

ldconfig

 Run the program and the result is as expected.

Five, dynamic library loading

1. The process of dynamic library loading

 When an executable file is compiled using a dynamic library, the executable file is stored on disk and loaded into memory at runtime.

We know that after the program is loaded into the memory, it becomes a process, and the OS will create the corresponding task_struct , mm_struct , and  page table   in the memory . When the user executes the code in the program, it executes normally. When the code in the dynamic library needs to be executed, the OS will find the dynamic library, load the dynamic library into the memory, and establish a page table mapping relationship, and map it to the shared area of ​​the virtual address space . These actions are automatically completed by the OS.

 When the executable file is compiled, it already has the corresponding virtual address. After the above actions are completed, execute the code in the dynamic library, and the OS will automatically recognize it and jump to the shared area of ​​the virtual address. Through the mapping relationship of the page table, execute the corresponding dynamic library code in the memory, and the dynamic library code is executed. After that, return to the code area part of the virtual address, and continue to execute other codes below.

 In other words, as long as the library is loaded into the memory and mapped to the address space of the process, the process executes the method in the library, and the function jump is still performed in its own address space.

 So the reason why the dynamic library saves resources is that all the methods in the dynamic library only need to be stored in one copy in the memory, and all other processes can be called.

2. Understanding of dynamic library address

 When the program is compiled and linked to form an executable program, the executable program already has an address inside. There are two types of addresses, namely absolute addressing and relative addressing.

 The dynamic library must face a problem: different processes have different operating levels, and the third-party libraries that need to be used are different, which means that the free space in the shared area of ​​each process is doomed to be uncertain. Therefore, the address of the function in the dynamic library must not use absolute addressing. All addresses in the dynamic library are offsets, starting from 0 by default. Simply put, the functions in the library only need to record their own offset in the library, that is, the relative address.

 When a library is actually mapped into the process address space, its starting address can be truly determined and managed by the OS. The OS itself manages the library, so the OS knows which library we use when we call the function in the library, and what the starting address of the library is. When you need to execute a function in the library, you only need to get the starting address of the library and add the offset of the corresponding function in the library to call the corresponding function.

 With the help of the relative address of the function in the library, no matter where the library is loaded into the shared area, it will not affect us to find the corresponding function accurately. So this kind of library is called a dynamic library, and the address in the dynamic library is called a position-independent code.

3. Supplementary content

  1.  Dynamic libraries and static libraries exist at the same time, and dynamic links are used by default. If you want to use static linking, you need to add the -static command option when compiling .
  2. If no dynamic library is provided, only a static library is provided, and the -static command option  is not added when compiling . Then when the program is linked, static linking will be used by default for this library. For others, such as C libraries, etc., dynamic linking is still used by default.

 That’s all for the relevant content about the dynamic and static libraries. I hope you will support me a lot. If there is something wrong, please correct me, thank you!

Guess you like

Origin blog.csdn.net/weixin_74078718/article/details/130391040