The netcore project calls the linux dynamic library under linux

The content of the article may look boring, and there are some problems in the typesetting, but if you encounter related problems and really can’t solve them, you might as well calm down and read this article carefully, you will gain something, and you can jump first Go to the end of the article and see if it is of value to your question. .

Use the P/invoke method

If the call fails, it may be that the so file lacks some dependent files, which can be viewed through the ldd command

ldd libzmq.so

If some dependent files cannot be found, the words not found will appear, such as the following

/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by */3rd-party/protobuf-2.4.1/src/.libs/libprotobuf.so.7)
/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by */3rd-party/protobuf-2.4.1/src/.libs/libprotoc.so.7)

You can use the string command to find out if a dependency is indeed missing

strings /usr/lib64/libstdc++.so.6 |grep GLIBCXX 得到结果
 
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_DEBUG_MESSAGE_LENGTH

The file is indeed missing. In this case, we need to use the find command to find the dependent file

find / -name libstdc++.so.6*

If you can find the dependent so file, you can use the cp command to copy the file to the lib64 directory

cp /usr/local/lib64/libstdc++.so.6.0.20 /usr/lib64 //复制文件

The system directory under Centos is /usr/lib64, the system directory may be different under Suse

If there are old files, you can use the rm command to delete the old files first

sudo rm -rf /usr/lib64/libstdc++.so.6  //删除旧文件

Finally, use the ln command to link to the new file

sudo ln -s /usr/lib64/libstdc++.so.6.0.20 /usr/lib64/libstdc++.so.6 //链接到新版本 (libstdc++.so.6.0.20是复制到linux中的文件的文件名)

After all these are done, you can test whether the dlopen command can open the file normally. If it can be opened normally, then the dllimport method can be used normally.

The source code of dllimport has not been developed, and it is suspected that it also calls the dlopen command under linux to call the so file

In addition to directly using the dllimport method to call, you can also use the delegate method to call the so file

The following is the test code, which can be compared and completely explained. The p/invoke method calls the so file under .netcore

public class SoTester
     {
         private const string LibraryName = "libzmq";
 
         const int RTLD_NOW = 2; // for dlopen's flags
         const int RTLD_GLOBAL = 8;
 
         [DllImport(@"libdl.so.2")]
         public static extern IntPtr dlopen(string filename, int flags);
         [DllImport("libdl.so.2")]
         public static extern IntPtr dlsym(IntPtr handle, string symbol);
 
         [DllImport("libdl.so.2", EntryPoint = "dlopen")]
         private static extern IntPtr UnixLoadLibrary(String fileName, int flags);
 
         [DllImport("libdl.so.2", EntryPoint = "dlclose", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
         private static extern int UnixFreeLibrary(IntPtr handle);
 
         [DllImport("libdl.so.2", EntryPoint = "dlsym", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
         private static extern IntPtr UnixGetProcAddress(IntPtr handle, String symbol);
 
         [DllImport("libdl.so.2", EntryPoint = "dlerror", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
         private static extern IntPtr UnixGetLastError();
 
         public delegate int sumHandler(int a, int b);
         public static sumHandler sumfunc = null;
 
         [DllImport("libNativeLib.so", EntryPoint = "sum", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
         public static extern int Sum(int a, int b);
 
         public void Start()
         {
             IntPtr libPtr = IntPtr.Zero;
 
             string libName = $"{AppContext.BaseDirectory}libNativeLib.so";
 
             libPtr = UnixLoadLibrary(libName, 2 | 8);
 
             //libPtr = dlopen(libName, RTLD_NOW);
 
             if (libPtr != IntPtr.Zero)
                 Console.WriteLine($"调用dlopen打开{libName}成功");
             else
                 Console.WriteLine($"调用dlopen打开{libName}失败");
 
             var sumPtr = UnixGetProcAddress(libPtr, "sum");
 
             if (sumPtr != IntPtr.Zero)
                 Console.WriteLine($"dlopen调用sum成功");
             else
                 Console.WriteLine($"dlopen调用sum失败");
 
             sumfunc = Marshal.GetDelegateForFunctionPointer<sumHandler>(sumPtr);
 
             int ret = sumfunc(1, 3);
 
             Console.WriteLine($"调用sum结果:{ret}");
 
             var sumRet = Sum(5, 7);
 
             Console.WriteLine($"DllImport调用sum结果:{sumRet}");
 
             //var libname2 = $"libc.so.6";
             var libname2 = $"{AppContext.BaseDirectory}libzmq.so";
             //var libname2 = $"{AppContext.BaseDirectory}libAdminConsole.so";
             var consolePtr = UnixLoadLibrary(libname2, 2 | 8);
             var erroPtr = UnixGetLastError();
             Console.WriteLine($"错误描述:{Marshal.PtrToStringAnsi(erroPtr)}");
 
             if (consolePtr != IntPtr.Zero)
                 Console.WriteLine($"打开{libname2}成功");
             else
                 Console.WriteLine($"打开{libname2}失败");
         }
   }

ps: At present, I have tested CentOS7 and suse12 SP3. Personally, if you need to use P/INVOKE in the project, it is best to run it on suse. The default gcc version of centos is relatively low, and it is very troublesome to upgrade gcc. All components of suse are complete, but the free version cannot update the components, and p/invoke can be used directly. Other versions of linux are not used.

Category:  NetCore

Compile with gcc under Linux to generate a dynamic link library *.so file and call it

  https://blog.csdn.net/flyztek/article/details/73612469

Compile with gcc under Linux to generate a dynamic link library *.so file and call it

Dynamic library *.so is often encountered when programming with c and c++ under linux. Recently, I found several articles on the website to introduce the compilation and linking of dynamic libraries. I finally understand this stuff that I didn’t know much about before. Here Make a note, and also provide a little help for other brothers who are troubled by the dynamic library link library.
1. Compilation of the dynamic library

The following uses an example to introduce how to generate a dynamic library. Here is a header file: so_test.h, three .c files: test_a.c, test_b.c, test_c.c, we compile these files into a dynamic library: libtest.so.

//so_test.h:
#include "stdio.h"
void test_a();
void test_b();
void test_c();

//test_a.c:
#include "so_test.h"
void test_a()
{   printf("this is in test_a...\n"); } //test_b.c: #include "so_test.h" void test_b() {   printf("this is in test_b...\n"); } //test_c. c: #include "so_test.h"

















  printf("this is in test_c...\n");
}
Compile these files into a dynamic library: libtest.so
$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so

2. The link of the dynamic library
In 1., we have successfully generated a dynamic link library libtest.so of our own. Next, we call the functions in this library through a program. The source file of the program is: test.c.

test.c:
#include "so_test.h"
int main()
{ test_a(); test_b(); test_c(); return 0; } Link test.c with dynamic library libtest.so to generate executable file test: $ gcc test.c -L. -ltest -o test to test whether it is dynamically connected. If libtest.so is listed, then the connection should be normal. $ ldd test Execute the test, and you can see how it calls the functions in the dynamic library. 3. Compilation parameter analysis The most important thing is an option of the GCC command line: -shared This option specifies to generate a dynamic link library (let the linker generate a T type export symbol table, and sometimes generate a weakly link W type export symbol), External programs cannot connect without this flag. equivalent to an executable














-fPIC: Indicates that the compiled code is position-independent. If this option is not used, the compiled code is position-dependent, so the code copy is used to meet the needs of different processes during dynamic loading, and the purpose of real code segment sharing cannot be achieved. .

-L.: Indicates that the library to be linked is in the current directory

-ltest: The compiler has an implicit naming rule when searching for a dynamic link library, that is, add lib in front of the given name, and add .so after it to determine the name of the library Name

LD_LIBRARY_PATH: This environment variable indicates the path where the dynamic linker can load the dynamic library.

Of course, if you have root authority, you can modify the /etc/ld.so.conf file, and then call /sbin/ldconfig to achieve the same purpose, but if you do not have root authority, you can only use the method of outputting LD_LIBRARY_PATH.

4. Note that

there are several problems often encountered when calling a dynamic library. Sometimes, the directory where the header file of the library is located has been included through "-I" include, and the file where the library is located is guided by the "-L" parameter and specified "-l" library name, but when viewed through the ldd command, the so file you specified for the link cannot be found. What you need to do at this time is to specify it by modifying the LD_LIBRARY_PATH or /etc/ld.so.conf file The directory of the dynamic library. Usually doing this can solve the problem that the library cannot be linked.

In linux, you can use the export command to set this value, enter in the linux terminal:
export LD_LIBRARY_PATH=/opt/au1200_rm/build_tools/bin: $LD_LIBRARY_PATH:   
and then enter: export   
and it will display whether the setting is correct   
The export method will fail after restarting, so you can also use vim /etc/bashrc to modify the LD_LIBRARY_PATH variable.   
For example: LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/au1200_rm/build_tools/bin.

Basic concepts of static libraries, dynamic libraries, and libraries under the arm platform under Linux

1. Basic concepts

1.1, what is a library

 There are a large number of libraries under both the windows platform and  the Linux platform.

Essentially, a library is a binary form of executable code that can be loaded into memory by the operating system for execution.

Since the platforms of windows and  linux  are different (mainly the differences in compilers, assemblers and linkers), the binaries of the two libraries are not compatible.

This article is limited to the library under linux.

1.2. Types of libraries

There are two types of libraries under linux: static libraries and shared libraries (dynamic libraries).

The difference between the two lies in the moment when the code is loaded.

The code of the static library has been loaded into the executable program during the compilation process, so the size is relatively large.

Static with .a as the suffix, for example: libhello.a

The code of the shared library (dynamic library) is loaded into the memory when the executable program is running, and it is only simply referenced during the compilation process, so the code size is small.

Dynamic is usually suffixed with .so, for example: libhello.so

The advantage of a shared library (dynamic library) is that if different applications call the same library, only one instance of the shared library needs to be stored in memory.

In order to use different versions of the library in the same system, you can add the version number as the suffix after the library file name, for example: libhello.so.1.0, because the program connection defaults to .so as the file suffix. So in order to use these libraries, the way of establishing symbolic links is usually used.

ln -s libhello.so.1.0 libhello.so.1 ln -s libhello.so.1 libhello.so

1.3. How are static library and dynamic library files generated under linux:

Take the following code as an example to generate the hello library used above:

/* hello.c */ 

#include "hello.h" 

void sayhello() 

printf("hello,world "); 

}

First, use gcc to compile the file, and you can use any legal compilation parameters when compiling, such as -g to add debugging code, etc.:

$gcc -c hello.c -o hello.o

1. Generate a static library Use the ar tool to generate a static library. In fact, ar means archive

$ar cqs libhello.a hello.o

2. Generate a dynamic library. Use gcc to complete it. Since there may be multiple versions, the version number is usually specified:

$gcc -shared -o libhello.so.1.0 hello.o

1.4. How are library files named? Is there any specification?

Under linux, library files are generally placed under /usr/lib and /lib,

The name of the static library is generally libxxxx.a, where xxxx is the name of the lib;

The name of the dynamic library is generally libxxxx.so.major.minor, where xxxx is the name of the lib, major is the major version number, and minor is the minor version number

1.5. How to locate the shared library (dynamic library) file when the executable program is executed:

When the system loads the executable code (that is, the library file), it can know the name of the library it depends on, but it also needs to know the absolute path. At this time, the system dynamic loader (dynamic linker/loader) is required.

For the executable program in elf format, it is completed by ld-linux.so*, which searches the DT_RPATH segment of the elf file—environment variable LD_LIBRARY_PATH—/etc/ld.so.cache file list—/lib/,/usr The /lib directory finds the library file and loads it into memory

Such as: export LD_LIBRARY_PATH='pwd'

Add the current file directory as a shared directory

1.6. Use the ldd tool to check which dynamic libraries the executable program depends on or which dynamic libraries the dynamic library depends on:

The ldd command can view the shared libraries that an executable program depends on,

For example # ldd /bin/lnlibc.so.6

=> /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2

=> /lib/ld- linux.so.2 (0×40000000)

You can see that the ln command depends on the libc library and the ld-linux library

Use the following command to view the dependencies of the arm platform

Note: arm-linux-readelf -d busybox | grep Shared can be omitted after grep, pay attention to the capitalization of the first letter of Shared

   

1.7. Use the nm tool to check the function names in the static library and dynamic library (T class indicates that the function is defined in the current library, U class indicates that the function is called and defined in other libraries, W class is the current library defined in and overridden by functions in other libraries). :

Sometimes you may need to check what functions are in a library. The nm tool can print out all the symbols involved in the library. The library here can be either static or dynamic.

There are many symbols listed in nm, and there are three common ones::

One is called in the library, but not defined in the library (indicating the need for other library support), represented by U;

One is the function defined in the library, represented by T, which is the most common;

The other is the so-called "weak state" symbols. Although they are defined in the library, they may be overwritten by symbols of the same name in other libraries, represented by W.

For example, suppose a developer wants to know whether printf() is referenced in the hello library mentioned above:

$nm libhello.so | grep printf

It is found that printf is a U-type symbol, indicating that printf is referenced, but it is not defined in the library.

It can be inferred from this that in order to use the hello library normally, there must be other library support. Use the ldd tool to check which libraries hello depends on:

$ldd hello libc.so.6=>/lib/libc.so.6(0x400la000) /lib/ld-linux.so.2=>/lib/ld-linux.so.2 (0x40000000)

From the above results, you can continue to see where printf is finally defined. If you are interested, you can Go  on

1.8. Using the ar tool, you can generate a static library, and at the same time, you can check which .o files are included in the static library, that is, which source files are composed.

You can use ar -t libname.a to see which .o files constitute a static library.

A static library can be generated with ar q libname.a xxx1.o xxx2.o xxx3.o ... xxxn.o

When programming under Linux, about the use of libraries:

1. The parameters of the library in the gcc/g++ command:

-shared: This option specifies to generate a dynamic link library (let the linker generate a T-type export symbol table, and sometimes generate a weak connection W-type export symbol), and the external program cannot be connected without this flag. equivalent to an executable

-fPIC: Indicates that the code is compiled into position-independent (address-independent) code. If this option is not used, the compiled code is position-dependent. Therefore, when dynamic loading is performed, the code is copied to meet the needs of different processes, and cannot To achieve the purpose of real code segment sharing.

-L: Specify the path of the link library, -L. means that the library to be linked is in the current directory

-ltest: Specify the name of the link library as test. The compiler has an implicit naming rule when searching for a dynamic link library, that is, add lib in front of the given name, and add .so after it to determine the name of the library

LD_LIBRARY_PATH: This environment variable indicates the path where the dynamic linker can load the dynamic library.

Of course, if you have root authority, you can modify the /etc/ld.so.conf file, and then call /sbin/ldconfig to achieve the same purpose,

However, if you do not have root privileges, you can only use the method of modifying the LD_LIBRARY_PATH environment variable.

When calling a dynamic library, there are several problems that are often encountered:

1. Sometimes, it is obvious that the directory where the header file of the library is located has been entered through "-I" include, the file where the library is located is guided by the "-L" parameter, and the library name of "-l" is specified, but when viewed through the ldd command , that is, you can’t find the so file you specified for the link. What you have to do at this time is to specify the directory of the dynamic library by modifying the LD_LIBRARY_PATH or /etc/ld.so.conf file. Usually doing this can solve the problem that the library cannot be linked.

2. The order of the search path when linking static libraries:

1. ld will look for the parameter -L in the gcc/g++ command;

2. Look for the environment variable LIBRARY_PATH of gcc, which specifies the search path for the static link library file of the program;

export LIBRARY_PATH=$LIBRARY_PATH:data/home/billchen/lib

3. Find the default library directory /lib /usr/lib /usr/local/lib, which was written in the program when compiling gcc.

3. Search path order during dynamic linking and execution:

1. The dynamic library search path specified when compiling the object code;

2. The environment variable LD_LIBRARY_PATH specifies the dynamic library search path, which specifies the program dynamic link library file search path;

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:data/home/billchen/lib

3. The dynamic library search path specified in the configuration file /etc/ld.so.conf;

4. The default dynamic library search path /lib;

5. The default dynamic library search path /usr/lib.

Fourth, the problems of static library and dynamic link library at the same time:

When a library exists both static library and dynamic library, for example, when libmysqlclient.a and libmysqlclient.so exist at the same time:

Under Linux, when the dynamic library and the static library exist together, the gcc/g++ linker will link the dynamic library by default.

You can use the following method to pass parameters to the linker to see whether to link the dynamic library or the static library.

-WI,-Bstatic -llibname //Specify to let gcc/g++ link the static library

use:

gcc/g++ test.c -o test -WI,-Bstatic -llibname

-WI,-Bdynamic -llibname //Specify to let gcc/g++ link dynamic library

use:

gcc/g++ test.c -o test -WI,-Bdynamic -llibname

If you want to add it completely statically, use the -static parameter, that is, link all libraries into the executable program in a static manner, so that the generated executable program no longer depends on any library. The problem that colleagues have is that the program compiled in this way Very large and takes up space.

5. Relevant environment variables:

LIBRARY_PATH environment variable: specify the program static link library file search path

LD_LIBRARY_PATH environment variable: specify the program dynamic link library file search path

6. Dynamic library upgrade problem:

When the dynamic link library is upgraded,

You cannot use cp newlib.so oldlib.so, which may make the program core drop;

Instead you should use:

rm oldlib.so then cp newlib.so oldlib.so

or

mv oldlib.so oldlib.so_bak then cp newlib.so oldlib.so

Why can't cp newlib.so oldlib.so be used?

When replacing the so file, if the dynamic library file used by the program is directly replaced by cp new.so old.so without stopping the program, the running program will crash.

Solution:

The solution is to use "rm+cp" or "mv+cp" to replace the direct "cp" operation method.

There are two ways to use the dynamic library of the linux system: dynamically link the library at runtime, dynamically load the library and use it under program control.

1. Why does the cp command directly replace the so file used by the program when the program is not stopped, causing the program to crash?

Many students have encountered such a problem in their work. When replacing the so file, if the dynamic library file used by the program is directly replaced by cp new.so old.so without stopping the program, it will cause the running The program crashes, exiting.

This is related to the implementation of the cp command. cp does not change the inode of the target file, and the target file of cp will inherit the attributes of the overwritten file instead of the source file. In fact it is implemented like this:

strace cp libnew.so libold.so 2>&1 |grep open.*lib.*.so

open("libnew.so", O_RDONLY|O_LARGEFILE) = 3

open("libold.so", O_WRONLY|O_TRUNC|O_LARGEFILE) = 4

When cp uses "O_WRONLY|O_TRUNC" to open the target file, the image of the original so file is accidentally destroyed. In this way, the dynamic linker ld.so cannot access the function entry in the so file. This leads to Segmentation fault and the program crashes. The mechanism of ld.so loading so files and "relocation" is more complicated.

2. How to replace the so file without stopping the program, and ensure that the program will not crash?

The answer is to use "rm+cp" or "mv+cp" to replace the direct "cp" operation method.

When replacing the old so file libold.so with the new so file libnew.so, if the following method is used:

rm libold.so //If the kernel is using libold.so, the inode node will not be deleted immediately.

cp libnew.so libold.so

With this method, the inode of the target file libold.so has actually changed. Although the original libold.so file cannot be viewed with "ls", its inode has not been deleted until the kernel releases its reference.

(That is: rm libold.so, at this time, if ld.so is being added to libold.so, the kernel is referencing the inode node of libold.so, the inode of rm libold.so has not been actually deleted, when ld.so is right The inode will actually be deleted when the reference of libold.so ends. This way the program will not crash, because it is still using the old libold.so. When libold.so is used next time, it has been replaced and the new libold will be used .so)

In the same way, mv just changes the file name, its inode remains unchanged, and the new file uses a new inode. In this way, the dynamic linker ld.so still uses the inode of the original file to access the old so file. So the program can still run normally.

(That is: after mv libold.so ***, if the program uses a dynamic library, it still uses the old inode node. When libold.so is used next time, the new libold.so will be used)

At this point, why does the system prohibit such operations when using the command "cp new_exec_file old_exec_file" directly, and give the prompt "cp: cannot create regular file `old': Text file busy". At this time, the method we adopt is still to use "rm+cp" or "mv+cp" to replace the direct "cp", which is the same as the replacement of the so file mentioned above.

But why does the system prevent cp from covering executable programs but not so files?

This is because Linux has a Demand Paging mechanism. The so-called "Demand Paging" simply means that in order to save physical memory overhead, the system does not load all pages (pages) into memory when the program is running, but only when the program is running. It is only loaded when the system has access requirements. "Demand Paging" requires that the running program image (note, not the file itself) is not accidentally modified, so the kernel will lock the inode of the program image after starting the program.

For the so file, it is loaded by ld.so, and ld.so is also a user-mode program after all, and has no right to lock the inode, and should not be coupled with the underlying file system of the kernel.

gcc specifies the header file path and the dynamic link library path

   

This article introduces in detail the method of specifying the gcc header file under linux, and the order of the search path. In addition, it also summarizes the method of gcc dynamic linking and path specification, and also discusses the order of searching paths. This article contains a lot of examples, which are highly operable, and I hope readers can go through it by themselves.
1. #include <> and #include ""

#include <> Go directly to some directories specified by the system to find some header files.
#include ""First go to the folder where the source file is located, and then go to some directories specified by the system to find some header files.

2. Three situations in which gcc specifies the header file:

1. It will be assigned to the /usr/include folder by default (the deeper level is a relative path, the path of the gcc executable program is /usr/bin/gcc, then it specifies the header file header path when it actually works. A relative path method, converted to an absolute path is to add /usr/include, such as #include is to include /usr/include/stdio.h)

2. GCC also uses -I to specify the path, that is,
the folder where the gcc -I header file is located (absolute path or relative path can be used) source file
As an example:
let the current path be /root/test, and its structure is as follows:
include_test.c
include/include_test.h
There are two ways to access include_test.h.
1. #include "include/include_test.h" in include_test.c and then gcc include_test.c
2. #include or #include in include_test.c and then gcc –I include include_test.c is also available

3. Parameters: -nostdinc makes the compiler no longer look for header files in the default header file directory of the system. It is generally used in conjunction with -I to clearly limit the location of header files.

When compiling the driver module, due to special requirements, GCC must be forced not to search the system default path, that is, to not search /usr/include, use the parameter -nostdinc, and use the -I parameter to specify the path of the kernel header file. At this time, you must Specify in Makefile.

Header file search order:
1. The path specified by the parameter -I (when the specified path has multiple paths, search in the order of the specified path)

2. Then find the gcc environment variables C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH

3. Find the default directory
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include
/usr/lib/gcc-lib/i386-linux/2.95.2 /../../../../include/g++-3
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux /include

Library files, but if there is a given prefix when installing gcc, then it is
/usr/include
prefix/include
prefix/xxx-xxx-xxx-gnulibc/include
prefix/lib/gcc-lib/xxxx-xxx- xxx-gnulibc/2.8.1/include

3. Linux specifies the dynamic library path

As we all know, the default search paths for Linux dynamic libraries are /lib and /usr/lib. After the dynamic library is created, it is generally copied to these two directories. When a program needs a dynamic library, and the dynamic library has not been loaded into the memory, the system will automatically search for the corresponding dynamic library file in the two default search paths, and then load the file into the memory, so that the program Then you can use the functions in the dynamic library and other resources of the dynamic library. In Linux, besides the default search path, the dynamic library search path can also be specified by the following three methods.

1. Specify the dynamic library search path in the configuration file /etc/ld.so.conf.
You can specify the search path of the dynamic library by editing the configuration file /etc/ld.so.conf, each line in this file is a dynamic library search path. After editing the file each time, you must run the command ldconfig to make the modified configuration take effect.

Take an example:
All source files:
Source file 1: lib_test.c
#include 
void prt()
{ printf("You found me!!!/n"); } Source file 2: main.c void prt(); int main() { prt(); return 0; } Operation process: We use the source program lib_test.c to create the dynamic library lib_test.so through the following command. # gcc –o lib_test.o -c lib_test.c # gcc -shared -fPIC -o lib_test.so lib_test.o #Or a direct instruction: #gcc –shared –fPIC –o lib_test.so lib_test.c #
















Note:
The -fPIC parameter declares that the code segment of the link library can be shared, and
the -shared parameter declares that it is compiled as a shared library. Please note that the name of the shared library we compiled this time is called
lib_test.so, which is also a naming convention for Linux shared libraries: the suffix uses so, and the name uses the libxxxx format.

Then compile main.c with the following command to generate the target program main.out.
# gcc -o main.out -L. –l_test main.c
#

Note why -l_test?

Then move the library files to the directory /root/lib.
# mkdir /root/lib
# mv lib_test.so /root/lib/ lib_test.so
#

Finally, edit the configuration file /etc/ld.so.conf, and add a line /root/lib to the file.

Run the program main.out:
# ./main.out
./main.out: error while loading shared libraries: lib_test.so: cannot open shared object file: No such file or directory
#An
error occurred, the system did not find the dynamic library lib_test. so. Looking for the reason, it turns out that after editing the configuration file /etc/ld.so.conf, the command ldconfig was not run, so the modification just now has not yet taken effect. Let's try again after running ldconfig.

# ldconfig
# ./main.out
You found me!!!
#The
program main.out runs successfully and prints out the correct result.

2. Specify the dynamic library search path through the environment variable LD_LIBRARY_PATH.
The dynamic library search path can also be specified by setting the environment variable LD_LIBRARY_PATH. When multiple dynamic library search paths are specified through this environment variable, the paths are separated by a colon ":". The method is illustrated by Example 2 below.

Give an example:
This time we move the file lib_test.so obtained above to another place, such as under /root, and then set the environment variable LD_LIBRARY_PATH to find lib_test.so. The method of setting the environment variable is as follows:
# export LD_LIBRARY_PATH=/root
#Then
run:
#./main.out
You found me!!!
#Note
: It is not possible to set the environment variable LD_LIBRARY_PATH=/root, it must be exported.

3. Specify the dynamic library search path of the program when compiling the object code.
You can also specify the program's dynamic library search path when compiling the object code. -Wl, indicating that the following parameters will be passed to the link program ld (because gcc may automatically call ld). Here, the parameter "-Wl, -rpath," of gcc is used to specify
an example:
this time we also move the file lib_test.so obtained above to another place, such as under /root/test/lib,
because we need to Specify the dynamic library search path of the executable file when compiling the object code, so you need to recompile the source program main.c (see procedure 2) with the gcc command to generate the executable file main.out.
# gcc -o main.out -L. –l_test -Wl,-rpath,/root/test/lib main.c
#

Running result:
# ./main.out
You found me!!!
#

The program ./main.out runs successfully, and the output result is exactly the running result of the function prt in main.c. Therefore, the dynamic library searched by the program main.out is /root/test/lib/lib_test.so.

Regarding the use of -Wl, rpath, let me give another example. It should not be difficult to see the method of specifying multiple paths:
gcc -Wl,-rpath,/home/arc/test,-rpath,/lib/,-rpath ,/usr/lib/,-rpath,/usr/local/lib test.c

The above introduces three methods of specifying the dynamic library search path, plus the default dynamic library search path /lib and /usr/lib, a total of five dynamic library search paths, so what is the order of their search? Readers can use the following method to experiment:
(1) Generate 5 lib_test.so with the method introduced above and place them under 5 different folders, requiring each lib_test.so to have a unique search path, and pay attention to the main The output of the .out program is different.
(2) Run main.out, you can see that it is under the search path, then delete lib_test.so under this path, and then run it again. By analogy, the search order can be deduced.

It can be concluded that the search sequence of the search path of the dynamic library is:

1. The dynamic library search path specified when compiling the object code;

2. The dynamic library search path specified by the environment variable LD_LIBRARY_PATH;

3. The dynamic library search path specified in the configuration file /etc/ld.so.conf;

4. The default dynamic library search path /lib;

5. The default dynamic library search path /usr/lib.

When the dynamic library search path is specified in the above 1, 2, and 3, multiple dynamic library search paths can be specified, and the search sequence is based on the sequence of the specified paths. Interested readers verify for themselves.

Guess you like

Origin blog.csdn.net/baidu_38493460/article/details/130369208
Recommended