• dlopen重复打开的一些问题


    dlopen重复打开的一些问题

    源码地址: https://gitee.com/layty/test-dlopen
    如果打开多个动态库(软连接的),会共享内存吗?

    结论: 会

    如果动态库更新了,不close,直接open,会更新吗?

    结论: 不会,要先close,再open即可

    动态库源码如下

    #include <iostream>
    extern "C"{
    void say_hello(){
        static int i=0;
        std::cout << "Hello, from dlopen!" << i++ << std::endl;
    }
    }
    

    一个动态库打开多次

    结论:同一个句柄,这个直接在man手册有讲的

    #include <iostream>
    #include <dlfcn.h>    // dlopen, dlerror, dlsym, dlclose
    typedef void(*say_hello)(void);
    const char* dllPath = "./libdlopen.so";
    int main()
    {
        for(int i=0;i<10;i++)
        {
            void* handle = dlopen( dllPath, RTLD_LAZY );
            if( !handle )
            {
                fprintf( stderr, "[%s](%d) dlopen get error: %s\n", __FILE__, __LINE__, dlerror() );
                exit( EXIT_FAILURE );
            }
            else
            {
                std::cout << "handle addr is " << handle << std::endl;
            }
            say_hello fun = (say_hello)dlsym( handle, "say_hello" );
            //std::cout << "handle addr is close " << handle << std::endl;
            //dlclose(handle);
        }
    }
    

    输出

    layty@ubuntu:~/work/Test/dlopen/build$ ./main1
    handle addr is 0x55692beb3ed0
    handle addr is 0x55692beb3ed0
    handle addr is 0x55692beb3ed0
    handle addr is 0x55692beb3ed0
    handle addr is 0x55692beb3ed0
    handle addr is 0x55692beb3ed0
    handle addr is 0x55692beb3ed0
    handle addr is 0x55692beb3ed0
    handle addr is 0x55692beb3ed0
    handle addr is 0x55692beb3ed0
    

    如果是关闭后重新打开呢

    //std::cout << "handle addr is close " << handle << std::endl;
    //dlclose(handle);
    

    输出还是

    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed0
    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed0
    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed0
    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed0
    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed0
    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed0
    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed0
    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed0
    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed0
    handle addr is 0x55725a3eaed0
    handle addr is close 0x55725a3eaed
    

    使用软连接创建多个动态库

    结论: 唯一的句柄,内存共享

    layty@ubuntu:~/work/Test/dlopen/build$ ln -s libdlopen.so libdlopen.so.2.so
    layty@ubuntu:~/work/Test/dlopen/build$ ln -s libdlopen.so libdlopen.so.3.so
    layty@ubuntu:~/work/Test/dlopen/build$ ln -s libdlopen.so libdlopen.so.4.so
    layty@ubuntu:~/work/Test/dlopen/build$ ln -s libdlopen.so libdlopen.so.5.so
    layty@ubuntu:~/work/Test/dlopen/build$ ln -s libdlopen.so libdlopen.so.6.so
    layty@ubuntu:~/work/Test/dlopen/build$ ln -s libdlopen.so libdlopen.so.7.so
    layty@ubuntu:~/work/Test/dlopen/build$ ln -s libdlopen.so libdlopen.so.8.so
    layty@ubuntu:~/work/Test/dlopen/build$ ln -s libdlopen.so libdlopen.so.9.so
    layty@ubuntu:~/work/Test/dlopen/build$ ln -s libdlopen.so libdlopen.so.0.so
    

    然后直接多次打开

    #include <iostream>
    #include <dlfcn.h>    // dlopen, dlerror, dlsym, dlclose
    
    
    typedef void(*say_hello)(void);
    const char* dllPath = "./libdlopen.so";
    
    int main()
    {
        for(int i=0;i<10;i++)
        {
            char dllPathsoft[100];
            snprintf(dllPathsoft,sizeof(dllPathsoft),"%s.%d.so",dllPath,i);
    
            void* handle = dlopen( dllPathsoft, RTLD_LAZY );
            if( !handle )
            {
                
                fprintf( stderr, "[%s](%d)@%s dlopen get error: %s\n", __FILE__, __LINE__, dllPathsoft,dlerror() );
                exit( EXIT_FAILURE );
            }
            else
            {
                std::cout << "handle addr is " << handle << std::endl;
            }
            say_hello fun = (say_hello)dlsym( handle, "say_hello" );
            //std::cout << "handle addr is close " << handle << std::endl;
            // dlclose(handle);
        }
    }
    

    输出

    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!0
    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!1
    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!2
    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!3
    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!4
    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!5
    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!6
    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!7
    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!8
    handle addr is 0x55acb4ee8ed0
    Hello, from dlopen!9
    

    如果中间close了呢

    内存映射的句柄还是一样,但是变量已经被释放了

    layty@ubuntu:~/work/Test/dlopen/build$ ./main4
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    handle addr is 0x55d04e7bbed0
    Hello, from dlopen!0
    handle addr is close 0x55d04e7bbed0
    

    复制动态库

    结论: 会有不同的地址映射

    cp  libdlopen.so libdlopen.so.10.so
    cp  libdlopen.so libdlopen.so.11.so
    cp  libdlopen.so libdlopen.so.12.so
    cp  libdlopen.so libdlopen.so.13.so
    cp  libdlopen.so libdlopen.so.14.so
    cp  libdlopen.so libdlopen.so.15.so
    cp  libdlopen.so libdlopen.so.16.so
    cp  libdlopen.so libdlopen.so.17.so
    cp  libdlopen.so libdlopen.so.18.so
    cp  libdlopen.so libdlopen.so.19.so
    

    测试代码

    #include <iostream>
    #include <dlfcn.h>    // dlopen, dlerror, dlsym, dlclose
    
    
    typedef void(*say_hello)(void);
    const char* dllPath = "./libdlopen.so";
    
    int main()
    {
        for(int i=10;i<20;i++)
        {
            char dllPathsoft[100];
            snprintf(dllPathsoft,sizeof(dllPathsoft),"%s.%d.so",dllPath,i);
    
            void* handle = dlopen( dllPathsoft, RTLD_LAZY );
            if( !handle )
            {
                
                fprintf( stderr, "[%s](%d)@%s dlopen get error: %s\n", __FILE__, __LINE__, dllPathsoft,dlerror() );
                exit( EXIT_FAILURE );
            }
            else
            {
                std::cout << "handle addr is " << handle << std::endl;
            }
            say_hello fun = (say_hello)dlsym( handle, "say_hello" );
            fun();
            //std::cout << "handle addr is close " << handle << std::endl;
            // dlclose(handle);
        }
    }
    

    输出

    layty@ubuntu:~/work/Test/dlopen/build$ ./main5 
    handle addr is 0x55e15ac76ed0
    Hello, from dlopen!0
    handle addr is 0x55e15ac77940
    Hello, from dlopen!0
    handle addr is 0x55e15ac77fa0
    Hello, from dlopen!0
    handle addr is 0x55e15ac78600
    Hello, from dlopen!0
    handle addr is 0x55e15ac78c60
    Hello, from dlopen!0
    handle addr is 0x55e15ac792c0
    Hello, from dlopen!0
    handle addr is 0x55e15ac79920
    Hello, from dlopen!0
    handle addr is 0x55e15ac79f80
    Hello, from dlopen!0
    handle addr is 0x55e15ac7a5e0
    Hello, from dlopen!0
    handle addr is 0x55e15ac7ac40
    Hello, from dlopen!0
    

    如果复制之后关闭呢

    可以看到句柄是一样的

    layty@ubuntu:~/work/Test/dlopen/build$ ./main6
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    handle addr is 0x564ba76c4ed0
    Hello, from dlopen!0
    handle addr is close 0x564ba76c4ed0
    

    动态更新动态库

    main7不close直接open 不会更新,也应该这样,否则内存什么的怎么处理

    再写一个so

    #include <iostream>
    
    extern "C"{
    
    void say_hello(){
        static int i=0;
        std::cout << "Hello, from dlopen new!" << i++ << std::endl;
    }
    
    }
    

    测试的源码

    #include <iostream>
    #include <dlfcn.h>    // dlopen, dlerror, dlsym, dlclose
    
    
    typedef void(*say_hello)(void);
    const char* dllPath = "./libdlopen.so.main7.so";
    
    int main()
    {
        for(int i=0;i<2;i++)
        {
            void* handle = dlopen( dllPath, RTLD_LAZY );
            if( !handle )
            {
                fprintf( stderr, "[%s](%d) dlopen get error: %s\n", __FILE__, __LINE__, dlerror() );
                exit( EXIT_FAILURE );
            }
            else
            {
                std::cout << "handle addr is " << handle << std::endl;
            }
            say_hello fun = (say_hello)dlsym( handle, "say_hello" );
            std::cout << "handle addr is close " << handle << std::endl;
            fun();
            
            std::cout << "wait to replace so " << handle << std::endl;
            getchar();
            dlclose(handle);
        }
    }
    

    执行如下

    ln -sf libdlopen.so  ./libdlopen.so.main7.so
    
    ln -sf libdlopen2.so  ./libdlopen.so.main7.so
    
    
    layty@ubuntu:~/work/Test/dlopen/build$ ./main7 
    handle addr is 0x55a2dd4f7ed0
    handle addr is close 0x55a2dd4f7ed0
    Hello, from dlopen!0
    wait to replace so 0x55a2dd4f7ed0
    ----------------------------------------------------------------使用软连接换掉so
    handle addr is 0x55a2dd4f7ed0
    handle addr is close 0x55a2dd4f7ed0
    Hello, from dlopen!1
    wait to replace so 0x55a2dd4f7ed0
    

    使用close再去打开main8

     ln -sf libdlopen2.so  
    layty@ubuntu:~/work/Test/dlopen/build$ ./main8
    handle addr is 0x55fec2ce8ed0
    handle addr is close 0x55fec2ce8ed0
    Hello, from dlopen!0
    wait to replace so 0x55fec2ce8ed0
    --------------------------------------------------这个地方使用 新开一个终端执行ln -sf libdlopen2.so  ./libdlopen.so.main7.so
    handle addr is 0x55fec2ce8ed0
    handle addr is close 0x55fec2ce8ed0
    Hello, from dlopen new!0-----------------------------可以看到so使用新的,类似于热更新了
    wait to replace so 0x55fec2ce8ed0
    
  • 相关阅读:
    MVC 下 JsonResult 的使用方法(JsonRequestBehavior.AllowGet)<转>
    MVC Razor模板引擎 @RenderBody、@RenderPage、@RenderSection及Html.RenderPartial、Html.RenderAction
    ASP.NET MVC路径引用总结
    XHTML 相对路径与绝对路径
    MVC中处理Json和JS中处理Json对象
    ASP.NET MVC中为DropDownListFor设置选中项的方法
    List转MVC DropDownListFor(SelectList)
    C# MVC 枚举转 SelectListItem
    MVC为Html对象建立一个扩展方法,使用自己的控件就像使用TextBox一样方便
    Java语言的主要特点
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/16415920.html
Copyright © 2020-2023  润新知