2

私はLinux(Ubuntu 12.04、gcc 4.6.3)を使用しており、必要に応じてプラグインをリロードできるプラグインベースのアプリケーションを作成するために、自分の意志に合わせてdlopen / closeを曲げようとしています(たとえば、再コンパイルされた場合) .

基本的な理論は単純です。プラグインを dlopen します。それを使用し、使用中のすべてのシンボルを追跡します。リロードするときが来たら、すべてのシンボルをクリーンアップし、プラグインを dlclose します。

簡単なデモ アプリ「test.cpp」をまとめました。

#include <dlfcn.h>
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
    if (argc > 1)
    {
        void* h = dlopen(argv[1], RTLD_NOW|RTLD_LOCAL);
        if (!h)
        {
            cerr << "ERROR: " << dlerror() << endl;
            return 1;
        }
        cin.get();
        if (dlclose(h))
        {
            cerr << "ERROR: " << dlerror() << endl;
            return 2;
        }
        cin.get();
    }
    return 0;
}

コンパイル:

g++ test.cpp -o test -ldl

上記のコードに引数として渡すことができる単純なライブラリを作成するには、次を使用します。

touch libtest.cpp && g++ -rdynamic -shared libtest.cpp -o libtest.so

次に、次のように実行します。

./test ./libtest.so

ここに問題があります。[Enter] を 1 回押した後 (つまり、ライブラリをロードしておそらくアンロードした後)、'pmap' を実行して 'test' にロードされているライブラリを確認すると、libtest.so がまだそこにあることがわかります! 現在、これは dlclose() からの有効な戻りにもかかわらず、参照カウントがそれより前に 1 を超えていた合理的な方法はありません (これは 2 番目の dlclose() を試行することで確認できます。閉まっている)。

したがって、Linuxが dlopen() されたライブラリをアンロードしない(ドキュメントと矛盾する) か、「pmap」が間違っています。後者の場合、ライブラリがまだロードされているかどうかを判断するより信頼できる方法はありますか?

4

1 に答える 1

2

私は以下のプログラムであなたと同じことを観察しません:

// file soq.c
#include <dlfcn.h>
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
using namespace std;
int main(int argc, char** argv)
{
  char cmd[60];
  snprintf(cmd, sizeof(cmd), "pmap %d", getpid());
    if (argc > 1)
    {
        void* h = dlopen(argv[1], RTLD_NOW|RTLD_LOCAL);
        if (!h)
        {
            cerr << "ERROR: " << dlerror() << endl;
            return 1;
        }
    cerr << "after dlopen " << argv[1] << endl;
    system(cmd);
        cin.get();
        if (dlclose(h))
        {
            cerr << "ERROR: " << dlerror() << endl;
            return 2;
        }
        cin.get();
    cerr << "after close " << argv[1] << endl;
    system(cmd);
    }
    return 0;
}

予想通り、私は得ています:

% ./soq ./libempty.so
./soq ./libempty.so
after dlopen ./libempty.so
5276:   ./soq ./libempty.so
0000000000400000      8K r-x--  /home/basile/tmp/soq
0000000000601000      4K rw---  /home/basile/tmp/soq
0000000001b4d000    132K rw---    [ anon ]
00007f1dbfd01000      4K r-x--  /home/basile/tmp/libempty.so
00007f1dbfd02000   2044K -----  /home/basile/tmp/libempty.so
00007f1dbff01000      4K rw---  /home/basile/tmp/libempty.so
00007f1dbff02000   1524K r-x--  /lib/x86_64-linux-gnu/libc-2.13.so
00007f1dc007f000   2048K -----  /lib/x86_64-linux-gnu/libc-2.13.so
00007f1dc027f000     16K r----  /lib/x86_64-linux-gnu/libc-2.13.so
00007f1dc0283000      4K rw---  /lib/x86_64-linux-gnu/libc-2.13.so
00007f1dc0284000     20K rw---    [ anon ]
00007f1dc0289000     84K r-x--  /lib/x86_64-linux-gnu/libgcc_s.so.1
00007f1dc029e000   2048K -----  /lib/x86_64-linux-gnu/libgcc_s.so.1
00007f1dc049e000      4K rw---  /lib/x86_64-linux-gnu/libgcc_s.so.1
00007f1dc049f000    516K r-x--  /lib/x86_64-linux-gnu/libm-2.13.so
00007f1dc0520000   2044K -----  /lib/x86_64-linux-gnu/libm-2.13.so
00007f1dc071f000      4K r----  /lib/x86_64-linux-gnu/libm-2.13.so
00007f1dc0720000      4K rw---  /lib/x86_64-linux-gnu/libm-2.13.so
00007f1dc0721000    928K r-x--  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
00007f1dc0809000   2048K -----  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
00007f1dc0a09000     32K r----  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
00007f1dc0a11000      8K rw---  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
00007f1dc0a13000     84K rw---    [ anon ]
00007f1dc0a28000      8K r-x--  /lib/x86_64-linux-gnu/libdl-2.13.so
00007f1dc0a2a000   2048K -----  /lib/x86_64-linux-gnu/libdl-2.13.so
00007f1dc0c2a000      4K r----  /lib/x86_64-linux-gnu/libdl-2.13.so
00007f1dc0c2b000      4K rw---  /lib/x86_64-linux-gnu/libdl-2.13.so
00007f1dc0c2c000    128K r-x--  /lib/x86_64-linux-gnu/ld-2.13.so
00007f1dc0e1c000     20K rw---    [ anon ]
00007f1dc0e49000      8K rw---    [ anon ]
00007f1dc0e4b000      4K r----  /lib/x86_64-linux-gnu/ld-2.13.so
00007f1dc0e4c000      4K rw---  /lib/x86_64-linux-gnu/ld-2.13.so
00007f1dc0e4d000      4K rw---    [ anon ]
00007fff076c3000    132K rw---    [ stack ]
00007fff077b4000      4K r-x--    [ anon ]
ffffffffff600000      4K r-x--    [ anon ]
 total            15984K




after close ./libempty.so
5276:   ./soq ./libempty.so
0000000000400000      8K r-x--  /home/basile/tmp/soq
0000000000601000      4K rw---  /home/basile/tmp/soq
0000000001b4d000    132K rw---    [ anon ]
00007f1dbff02000   1524K r-x--  /lib/x86_64-linux-gnu/libc-2.13.so
00007f1dc007f000   2048K -----  /lib/x86_64-linux-gnu/libc-2.13.so
00007f1dc027f000     16K r----  /lib/x86_64-linux-gnu/libc-2.13.so
00007f1dc0283000      4K rw---  /lib/x86_64-linux-gnu/libc-2.13.so
00007f1dc0284000     20K rw---    [ anon ]
00007f1dc0289000     84K r-x--  /lib/x86_64-linux-gnu/libgcc_s.so.1
00007f1dc029e000   2048K -----  /lib/x86_64-linux-gnu/libgcc_s.so.1
00007f1dc049e000      4K rw---  /lib/x86_64-linux-gnu/libgcc_s.so.1
00007f1dc049f000    516K r-x--  /lib/x86_64-linux-gnu/libm-2.13.so
00007f1dc0520000   2044K -----  /lib/x86_64-linux-gnu/libm-2.13.so
00007f1dc071f000      4K r----  /lib/x86_64-linux-gnu/libm-2.13.so
00007f1dc0720000      4K rw---  /lib/x86_64-linux-gnu/libm-2.13.so
00007f1dc0721000    928K r-x--  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
00007f1dc0809000   2048K -----  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
00007f1dc0a09000     32K r----  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
00007f1dc0a11000      8K rw---  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
00007f1dc0a13000     84K rw---    [ anon ]
00007f1dc0a28000      8K r-x--  /lib/x86_64-linux-gnu/libdl-2.13.so
00007f1dc0a2a000   2048K -----  /lib/x86_64-linux-gnu/libdl-2.13.so
00007f1dc0c2a000      4K r----  /lib/x86_64-linux-gnu/libdl-2.13.so
00007f1dc0c2b000      4K rw---  /lib/x86_64-linux-gnu/libdl-2.13.so
00007f1dc0c2c000    128K r-x--  /lib/x86_64-linux-gnu/ld-2.13.so
00007f1dc0e1c000     20K rw---    [ anon ]
00007f1dc0e48000     12K rw---    [ anon ]
00007f1dc0e4b000      4K r----  /lib/x86_64-linux-gnu/ld-2.13.so
00007f1dc0e4c000      4K rw---  /lib/x86_64-linux-gnu/ld-2.13.so
00007f1dc0e4d000      4K rw---    [ anon ]
00007fff076c3000    132K rw---    [ stack ]
00007fff077b4000      4K r-x--    [ anon ]
ffffffffff600000      4K r-x--    [ anon ]
 total            13936K 

だからあなたはpmap 間違って走りました。

ところで、私のmanydl.cの例が示すdlcloseように、実際には -ing を避けることができます。実際には、気にしないことは、実際には大したことではなく、小さなアドレス空間リークを意味します。(ほぼ 100 万個の異なる共有オブジェクトをほとんど害することなく実行できます)。dlclosedlopen

また、共有オブジェクトがいつアンロードされるかを知るには、-d プラグインの「デストラクタ」関数dlclose(C++ の静的データのデストラクタ、Cコードattribute((destructor)) など)を使用します。荷降ろし。dlclose

于 2012-06-14T22:22:42.523 に答える