GNU/Linux >> Znalost Linux >  >> Linux

Jak vytvořit zpoždění sdílené knihovny načtené v systému Linux

Zpoždění načítání NENÍ funkce runtime. MSVC++ to implementovalo bez pomoci Windows. A jako dlopen je jediný způsob v Linuxu, GetProcAddress je jedinou runtime metodou ve Windows.

Co je tedy zpoždění načítání? Je to velmi jednoduché:Každé volání knihovny DLL musí projít ukazatelem (protože nevíte, kde se načte). To vždy za vás vyřešil kompilátor a linker. Ale se zpožděním načítání MSVC++ nastaví tento ukazatel zpočátku na stub, který volá LoadLibrary a GetProcAddress pro tebe.

Clang může udělat totéž bez pomoci ld . Za běhu je to jen obyčejný dlopen a Linux nemůže určit, že jej Clang vložil.


Chcete-li přidat k odpovědi MSalters, lze snadno napodobit přístup Windows k línému načítání v Linuxu vytvořením malé statické knihovny se zakázaným inzerováním, která by se pokusila dlopen potřebnou knihovnu při prvním volání kterékoli z jejích funkcí (vyslání diagnostické zprávy a ukončení, pokud selže dlopen) a následné přesměrování všech volání na ni.

Takové útržkové knihovny lze psát ručně, generovat skriptem specifickým pro projekt/knihovnu nebo generovat univerzálním nástrojem Implib.so:

$ implib-gen.py libxyz.so
$ gcc myapp.c libxyz.tramp.S libxyz.init.c ...

Této funkce lze dosáhnout přenosným způsobem pomocí návrhového vzoru proxy.

V kódu to může vypadat nějak takto:

#include <memory>

// SharedLibraryProxy.h
struct SharedLibraryProxy
{
    virtual ~SharedLibraryProxy() = 0;

    // Shared library interface begin.
    virtual void foo() = 0;
    virtual void bar() = 0;
    // Shared library interface end.

    static std::unique_ptr<SharedLibraryProxy> create();
};

// SharedLibraryProxy.cc
struct SharedLibraryProxyImp : SharedLibraryProxy
{
    void* shared_lib_ = nullptr;
    void (*foo_)() = nullptr;
    void (*bar_)() = nullptr;

    SharedLibraryProxyImp& load() {
        // Platform-specific bit to load the shared library at run-time.
        if(!shared_lib_) { 
            // shared_lib_ = dlopen(...);
            // foo_ = dlsym(...)
            // bar_ = dlsym(...)
        }
        return *this;
    }

    void foo() override {
        return this->load().foo_();
    }

    void bar() override {
        return this->load().bar_();
    }
};

SharedLibraryProxy::~SharedLibraryProxy() {}

std::unique_ptr<SharedLibraryProxy> SharedLibraryProxy::create() {
    return std::unique_ptr<SharedLibraryProxy>{new SharedLibraryProxyImp};
}

// main.cc
int main() {
    auto shared_lib = SharedLibraryProxy::create();
    shared_lib->foo();
    shared_lib->bar();
}

Linux
  1. Jak učinit starý počítač opět užitečným

  2. Jak nainstalovat knihovnu Ncurses v Linuxu

  3. Dynamická sdílená knihovna C++ v systému Linux

  1. Jak zpřístupnit sdílený adresář pomocí Sftp?

  2. Jak inicializovat sdílenou knihovnu v Linuxu

  3. Jak vytvořit rozdílovou zálohu v linuxu?

  1. Linux – Jak upozornit Tr na znaky, které nejsou v ASCII (unicode)?

  2. Úvod do sdílených knihoven Linuxu (Jak vytvořit sdílené knihovny)

  3. Jak zobrazím seznam funkcí, které exportuje sdílená knihovna Linuxu?