zoukankan      html  css  js  c++  java
  • 动态链接--运行时加载dlopen

    前面我们在编译可执行文件时,如果可执行文件要依赖某个so。必须要通过-L指定so路径,并且-l指定so名字。

    而且在可执行文件运行时,要先加载so的load部分到进程地址空间。

    有一种方式可以在编译时不需要link so, 而且程序运行过程中去加载so。

    dlopen函数可以在进程运行过程中,打开so,将其加载到进程的地址空间,并完成初始化过程。

    如果dlopen中指定的路径是相对路径,那么按照LD_LIBRARY_PATH,/etc/ld.so.cache,/lib,/usr/lib顺序查找。否则直接打开so。

    dlsym返回so的符号的值,如果符号是函数和变量,返回符号和变量的地址;如果符号是常量,就返回常量的值。

    我们在前面写的消息队列msgsnd.c代码中稍作修改,以运行时加载libmsg.so。代码如下:

    #include <sys/prctl.h>

    #include <string.h>
    #include <stdio.h>
    #include <dlfcn.h>
    #include "msg.h"
    #define MSG_CREAT_PATH "/mnt/hgfs/share/test/list"
    #define MSG_RCV_ID 4
    #define MSG_SND_ID 3
    typedef int (*create_msg_queue)(const char *path, int proj_id);
    typedef int (*rcv_msg)(int id, FellowMsg *msg);
    typedef int (*snd_msg)(int id, FellowMsg *msg);
    typedef struct _MsgIf{
      create_msg_queue create;
      rcv_msg rcv;
      snd_msg snd;
    }MsgIf;
    MsgIf msgIf;
    void *fellow_listenning_msg(void *arg)
    {
      if(0 != prctl(PR_SET_NAME, (unsigned long)"fellow_process_msg"))
      {
        printf("prctl fail, errno:%d", errno);
      }
      int msg_q_id = msgIf.create(MSG_CREAT_PATH, MSG_RCV_ID);
      FellowMsg _fellowMsg;
      while (1)
      {
        memset(&_fellowMsg, 0, sizeof(FellowMsg));
        msgIf.rcv(msg_q_id, &_fellowMsg);
        if (CTRL_FEEDBACK ==_fellowMsg._msgType)
        {
          switch (_fellowMsg._ctlInfo.u._ctlFeedback)
          {
            case OPEN_DONE:
            printf("rcv OPEN_DONE:%d ", _fellowMsg._ctlInfo.param);
            break;
            case CLOSE:
            printf("rcv CLOSE_DONE:%d ", _fellowMsg._ctlInfo.param);
            break;
            case PLAY:
            printf("rcv PLAY_DONE:%d ", _fellowMsg._ctlInfo.param);
            break;
            default:
            break;

          }
        }

      }
    }
    void main(void)
    {
      void *handle = dlopen("/mnt/hgfs/share/test/msg/libmsg.so", RTLD_NOW);//打开libmsg.so
      if (NULL == handle)
      {
        printf("dlopen fail:%s ", dlerror());
        return;
      }
      msgIf.create = (create_msg_queue)dlsym(handle, "fellow_create_msg_queue");//获取符号的值。
      msgIf.rcv = (rcv_msg)dlsym(handle, "fellow_rcv_msg");
      msgIf.snd = (snd_msg)dlsym(handle, "fellow_send_msg");
      pthread_t thread_id;
      int snd_msg_q_id = msgIf.create(MSG_CREAT_PATH, MSG_SND_ID);
      printf("msgid:%d ",snd_msg_q_id);
      FellowMsg _fellowMsg;
      _fellowMsg._msgType = CTRL_CMD;
      _fellowMsg._ctlInfo.u._ctlCmd = OPEN;
      _fellowMsg._ctlInfo.param = 1;
      printf("create:%p, snd:%p, rcv:%p ", msgIf.create, msgIf.snd,msgIf.rcv);
      msgIf.snd(snd_msg_q_id, &_fellowMsg);
      pthread_create(&thread_id, NULL, fellow_listenning_msg, NULL);
      while (1)
      {
      }
      dlclose(handle);
    }

    那么在编译时我们不需要link so: gcc msgsnd.c -o msgsnd -ldl -pthread

  • 相关阅读:
    国内比较优秀的.net论坛源代码收集 [转]
    WEB项目的分拆和布署[转载]
    采用XHTML和CSS设计可重用可换肤的WEB站点
    定时提醒小程序:VBScript
    小集正则表达式
    OO的设计原则
    在.Net内部, 异步委托是如何使用多线程功能的?
    Asp.net工作流程
    漫谈面向对象基石之开闭原则(OCP)(转)
    SQL Server 2008事务日志的[RowLog Contents 0] 字段没人能解析出来?
  • 原文地址:https://www.cnblogs.com/fellow1988/p/6185011.html
Copyright © 2011-2022 走看看