Summary of calling dynamic library (.SO file) in Linux

Like window calling library files, under linux , there are also corresponding APIs that exist because of loading library files. They are mainly the following functions:

Function name Functional description
dlopen Open the object file so that it can be accessed by the program
dlsym dlopen Get the address of the function in the object file that executed  the function
dlerror

This function has no parameters, it will return a string when the previous error occurs, and at the same time it will be saved from memory

empty; returns NULL if no error occurs,

dlclose

Close the target file. If there is no need to call the shared object, the application can call this method to notify

The operating system no longer needs handles and object references. It is completely reference counted, so the same

Multiple users of a shared object will not conflict with each other (as long as one user is still using it,

it will be in memory). Any symbols resolved through a closed object  dlsym will no longer be available 

 Example code (soTest.c):

copy code

1 #include <stdio.h> 
 2 #include <dlfcn.h> 
 3 
 4 int main(int argc, char *argv[]){ 
 5 void * libm_handle = NULL; 
 6 float (*cosf_method)(float); 
 7 char *errorInfo; 
 8 float result; 
 9      
10 // The dlopen function also automatically resolves dependencies in shared libraries. That way, if you open an object that depends on other shared libraries, it will automatically load them. 
11 // The function returns a handle, which is used for subsequent API calls 
12 libm_handle = dlopen("libm.so", RTLD_LAZY ); 
13 // If a NULL handle is returned, it means that the object file cannot be found, and the process ends. Otherwise, a handle of the object will be obtained, and the object can be further inquired 
14 if (!libm_handle){ 
15 // If the NULL handle is returned, the reason why the object cannot be accessed can be obtained through the dlerror method 
16 printf("Open Error:%s. \n",dlerror()); 
17 return 0; 
18 } 
19
20 // Using the dlsym function, try to resolve symbols in the newly opened object file. You will get a valid pointer to the symbol, or get a NULL and return an error 
21 cosf_method = dlsym(libm_handle,"cosf"); 
22 errorInfo = dlerror();// Call the dlerror method and return an error message At the same time, the error information in the memory is cleared 
23 if (errorInfo != NULL){ 
24 printf("Dlsym Error:%s.\n",errorInfo); 
25 return 0; 
26 } 
27 
28 // Execute "cosf" Method 
29 result = (*cosf_method)(0.0); 
30 printf("result = %f.\n",result); 
31      
32 // After calling the target function in the ELF object, close access to it by calling dlclose 
33 dlclose(libm_handle); 
34 
35 return 0; 
36 }

copy code

       In this example, the "cosf" function in the math library (libm.so) is mainly called. The second parameter of the dlopen function indicates the mode of loading the library file. There are two main types: RTLD_LAZY suspends the decision, and waits until necessary Solve symbols; RTLD_NOW resolves immediately, resolves all outstanding symbols before returning. Also remember to quote the header file "#include <dlfcn.h>" (^_^) that contains the API.

      Compilation and execution results are as follows:

      If the library file name in line 12 of the code is changed to a library file that does not exist, the error result after running is as follows:

      If the function name in line 21 of the code is changed to a function name that does not exist, the error result after running is as follows:

     

      This article mainly briefly describes some basic knowledge and points of attention for calling SO library files under linux.

      This example passed the test under the 64 system of redhat 5.2.

Personal creation, welcome to point out mistakes. 
The ELF format is involved, and the gcc compilation options are to be added. A simple and practical explanation, I have a practical understanding of the so files under Linux. 
1. What is the so file? 
2. How to generate and use a so dynamic library file? 
3. Address space, and thread safety. 
4. Initialization and analysis of the library: 
5. Replace system functions with functions in our own library: 
//------ -------------------------------------------------- ----------------------- 
1. What is the so file? 
It is also an ELF format file, a shared library (dynamic library), similar to a DLL. Save resources, speed up, and simplify code upgrades. 
Knowing so much is enough, pragmatism. Wait for the impression to study the principle again. 
2. How to generate and use a so dynamic library file? 
First write a C file: sc 

C code   

favorite code

  1. #include <stdio.h>  
  2. int count;  
  3. void out_msg(const char *m)  
  4. {//Output 1 message in 2 seconds and count  
  5.  for(;;) {printf("%s %d\n", m, ++count); sleep(2);}  
  6. }  


Compile: Get the output file libs.o 
gcc -fPIC -g -c sc -o libs.o 
  
Link: Get the output file libs.so 
gcc -g -shared -Wl,-soname,libs.so -o libs.so libs. o -lc 

a header file:sh 

C code   

favorite code

  1. #ifndef _MY_SO_HEADER_  
  2. #define _MY_SO_HEADER_  
  3. void out_msg(const char *m);  
  4. #endif  


Another C file to refer to the functions in this library: ts.c 

C code   

favorite code

  1. #include <stdio.h>  
  2.  #include "s.h"  
  3.  int main(int argc, char** argv)  
  4.  {  
  5.   printf("TS Main\n");  
  6.   out_msg("TS ");  
  7.   sleep(5); //This sentence can be commented out, and it can be opened in Section 4.  
  8.   printf("TS Quit\n");  
  9.  }  


Compile and link this file: get the output file ts 
gcc -g ts.c -o ts -L. -ls 

execute ./ts, um: success. . . I almost 
got ts:error while loading shared libraries: libs.so: cannot open shared object file: No such file or directory 
The system cannot find the libs.so we defined ourselves, so tell him to modify the variable LD_LIBRARY_PATH, for convenience, write A script: e (the file name is e, too lazy to make it long) 
#!/bin/sh 
export LD_LIBRARY_PATH=${pwd}:${LD_LIBRARY_PATH} 
./ts 
execution: ./e & 
the screen starts to have The information is output. Of course, you can’t see TS Quit. The front is an infinite loop, 
and this sentence  will be used later

./e&, 
what will happen to the screen information at this time? How will the global variable count change? 
It will be that the two processes cross-output information, and their respective counts do not interfere with each other, although they refer to the same so file. 
That is to say, there is only one statement about whether the code is thread-safe, and there is no statement about whether the code is process-safe. 
4. Library initialization and analysis: 
Dynamic library loading and unloading under windows will have initialization functions and unloading functions to complete library initialization and resource recovery. Of course, Linux can also implement it. 

When the ELF file itself is executed, it will execute a _init() function and a _fini() function to complete this. We only need to  let the system execute our own functions at this time. 
Modify our previous sc file: 

C code   

favorite code

  1. #include <stdio.h>  
  2.  void my_init(void) __attribute__((constructor)); //tell gcc to throw this function into the init section  
  3.  void my_fini(void) __attribute__((destructor)); //tell gcc to throw this function into fini section  
  4.  void out_msg(const char *m)  
  5.  {  
  6.   printf(" Ok!\n");   
  7.  }  
  8.  int i; //still a counter  
  9.  void my_init(void)  
  10.  {  
  11.   printf("Init ... ... %d\n", ++i);  
  12.  }  
  13.  void my_fini(void)  
  14.  {  
  15.   printf("Fini ... ... %d\n", ++i);  
  16.  }  


There is no need to recompile libs.so and ts, which is much more convenient for code maintenance and upgrading. 
Then execute: ./e & 
you can see the screen output: (incomplete information, just the same order) 
Init 
Main 
OK 
Quit 
Fini 
can see that the initialization function and analysis function we defined have been executed, and it is at the front and Last. 
If the sleep(5) in sc is not commented out, then there is a chance: 
./e& 
./e& is executed twice in a row, then the initialization function and analysis function will also be executed twice, although the system only loads libs.so once. 
If the background process is killed during sleep, the parsing function will not be executed. 
5. Use the functions in our own library to replace the system functions: 
create a new file bc: we want to replace the system functions malloc and free (you can write a memory leak detection tool yourself) 

C code   

favorite code

  1. #include <stdio.h>  
  2.  void* malloc(int size)  
  3.  {  
  4.   printf("My malloc\n");  
  5.   return NULL;  
  6.  }  
  7.  void free(void* ad)  
  8.  {  
  9.   printf("My free\n");  
  10.  }  


The old rule, compile and link into a so file: get libb.so 
gcc -fPIC -g -c bc -o libb.o 
gcc -g -shared -Wl,-soname,libb.so -o libb.so -lc 
modify sc : Regenerate libs.so 

C code   

favorite code

  1. void out_msg()  
  2.  {  
  3.   int *p;  
  4.   p = (int*)malloc(100);  
  5.   free(p);  
  6.   printf("Stop Ok!\n");  
  7.  }  


Modify the script file e: 
#!/bin/sh 
export LD_PRELOAD=${pwd}libb.so:${LD_PRELOAD} 
export LD_LIBRARY_PATH=${pwd}:${LD_LIBRARY_PATH} 
./ts 
The key is on LD_PRELOAD, this path The specified so will be loaded before all so, and the symbols will override the symbols in the so files loaded later. This variable is ignored if the permissions of the executable are not appropriate (SID). 
Execution: ./e & 
Well, we can see that our malloc and free are working. 
That's all I can think of for now.

Guess you like

Origin blog.csdn.net/ayang1986/article/details/121992610
Recommended