Programación del sistema Linux C (12) acceso a la biblioteca del sistema

Varias funciones relacionadas con el acceso a la biblioteca del sistema son dlopen, dlsym, dlclose y dlerr. Estas funciones se utilizan principalmente para cargar la biblioteca de enlaces dinámicos. El surgimiento de la biblioteca del sistema es hacer que el programa sea fácil de expandir, con universalidad, puede usarse en forma de complementos. El modelo controlado por eventos asincrónicos se adopta para garantizar que la lógica del programa principal permanezca sin cambios y que varios negocios se hayan cargado dinámicamente en la biblioteca, que se denomina complemento. Linux proporciona una llamada al sistema para cargar y procesar bibliotecas de enlaces dinámicos, lo cual es muy conveniente.


1 Introducción a dlopen, dlsym, dlclose, dlerror

Es necesario incluir archivos de encabezado al usar: 

#include <dlfcn.h> 

1.1 Introducción a la función dlopen

@ 1 Definición básica: abrir una biblioteca de enlaces dinámicos

@ 2 Definición de función:

void * dlopen( const char * pathname, int mode ); 
函数描述: 在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。
注意:使用时最后需要dlclose()来卸载打开的库。
参数pathname:绝对路径
参数mode:分为这两种
   RTLD_LAZY 暂缓决定,等有需要时再解出符号 
   RTLD_NOW 立即决定,返回前解除所有未决定的符号。 
  RTLD_LOCAL 
  RTLD_GLOBAL 允许导出符号 
  RTLD_GROUP 
  RTLD_WORLD 
返回值:打开错误返回NULL,成功则返回库引用

Nota: cuando use esta serie de métodos, agregue -ldl (especifique la biblioteca dl) al compilar 

1.2 Introducción a la función dlsym

@ 1 Definición básica: según el identificador de operación y el símbolo de la biblioteca de enlace dinámico, devuelva la dirección correspondiente al símbolo.

@ 2 Definición de función:

void* dlsym(void* handle,const char* symbol);
函数描述:
dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。
使用这个函数不但可以获取函数地址,也可以获取变量地址。
参数handle:由dlopen打开动态链接库后返回的指针,
参数symbol:要求获取的函数或全局变量的名称。
返回值:查找到的对应函数或者变量地址值    

1.3 Introducción a la función dlclose

@ 1 Definición básica, cierre el controlador del enlace de la biblioteca dinámica

@ 2 Definición de función:

int dlclose (void *handle);
函数描述:
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
参数handle:需要关闭的动态库句柄
返回值:动态库卸载应用计数的返回值

1.4 Introducción a la función dlerror

@ 1 Definición básica: juicio de error y análisis de biblioteca dinámica

@ 2 Definición de función:

char *dlerror(void);
函数描述:当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
返回值:错误信息 或 NULL

2 ejemplos de uso de dlopen, dlsym, dlclose, dlerror

2.1 Casos de prueba de biblioteca dinámica

El prototipo de la función hello.c es el siguiente:  

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
typedef struct {
    const char *module;
    int  (*GetValue)(char *pszVal);
    int   (*PrintfHello)();
} hello_ST_API;

int GetValue(char *pszVal)
{
    int retval = -1;
    if (pszVal)
        retval = sprintf(pszVal, "%s", "123456");
        printf("%s, %d, pszVer = %s\n", __FUNCTION__, __LINE__, pszVal);
    return retval;
}

int PrintfHello()
{
    int retval = -1; 
    printf("%s, %d, hello everyone\n", __FUNCTION__, __LINE__);
    return 0;
}

const hello_ST_API  Hello = {
    .module = "hello",
    GetValue,
    PrintfHello,
};

Use las instrucciones al compilar:

gcc -fPIC -shared  -o hello.so hello.c

La función anterior es señalada por una estructura global hola. La definición de dlsym dice que no solo se puede obtener la dirección de la función sino también la dirección de la variable global. Así que aquí es para obtener la dirección de la variable global a través de dlsym (el uso más común)

2.2 Ejemplos de uso de bibliotecas dinámicas para dlopen, dlsym, dlclose y dlerror

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>

typedef struct {
    const char *module;
    //int (*GetValue)(char *pszVal);
    int (*PrintfHello)();
} hello_ST_API;

int main(int argc, char **argv)
{
    hello_ST_API *hello;
    int i = 0;
    void *handle;
    char psValue[20] = {0};
 
    handle = dlopen("库存放的绝对路径,你可以试试相对路径是不行的", RTLD_LAZY);
    if (!handle) {
        printf("%s,%d, NULL == handle\n", __FUNCTION__, __LINE__);
        return -1;
    }
    dlerror();
    hello = dlsym(handle, "Hello");
    if (!hello) {
        printf("%s,%d, NULL == handle\n", __FUNCTION__, __LINE__);
        return -1;
    }
    if (hello && hello->PrintfHello)
        i = hello->PrintfHello();
    printf("%s, %d, i = %d\n", __FUNCTION__, __LINE__, i);
    if (hello && hello->GetValue)
        i = hello->GetValue(psValue);
    if (hello && hello->module){
        printf("%s, %d, module = %s\n", __FUNCTION__, __LINE__, hello->module);
    }
    dlclose(handle);
    return 0;
}

Instrucciones de compilación:

gcc -o test hello_dlopen.c -ldl 

Nota especial: después de que dlsym encuentre la estructura global hola, puede usar el puntero de estructura global directamente para usar las funciones en la biblioteca, porque a veces la biblioteca que proporcionamos no es solo una o dos funciones, generalmente existirá una biblioteca Esta función se puede usar directamente de esta manera. De lo contrario, si desea encontrar el nombre de la función, escriba dlsym múltiple.

Publicado 289 artículos originales · elogiados 47 · 30,000+ vistas

Supongo que te gusta

Origin blog.csdn.net/vviccc/article/details/105171704
Recomendado
Clasificación