Shared Libraries: Windows vs Linux method

前端 未结 3 1059

I have a quick question about Windows shared libraries (DLLs) vs Linux shared libraries (SOs).

Why is it that when you create a Windows DLL it requires the client progra

相关标签:
3条回答
  • 2021-01-31 18:23

    Not actually with code relocation, that's a totally different issue. It is about a difference in architecture:

    • In Windows, a DLL is just like a executables (EXE). The main difference between an EXE and a DLL is that the EXE has an entry point (main/WinMain function) and so it can be used to start a process, while DLLs can only be loaded into a pre-existing process. But see (1)

    • In Linux, a .so work similar to a static library (.a). The main difference is that the .so file can be linked with a running program, while the .a file can only be linked when compiling the program.

    A consequence of this approach is that in linux the same file can be used to build and run the program. But in Windows you need a proper library (LIB) to link the program. Actually the lib that corresponds to a DLL usually have nothing more than the names of the functions, to satisfy the linker, and the stubs to do the relocation. But see (2)

    (1) Well, DLLs have entry point too, but it is not used as the main function, just as some sort of initialization/finalization hook.

    (2) Some linkers are smart enough to be able, in some simple cases, to link to a DLL by using the DLL itself, without the need of an additional LIB file. I think that at least the MinGW linker can do that.

    0 讨论(0)
  • 2021-01-31 18:28

    Why is it that when you create a Windows DLL it requires the client program to also link against a static library (.lib file), but applications created in Linux does not require any linking against such static library.

    This is a historic design decision made by Microsoft so that the linker could add DLL references into an executable without having a particular version of the DLL being present at link time. The reason for this was, that there always have been different versions of Windows around, with different versions of DLLs. Also at that time Microsoft was cooperating with IBM on OS/2 and the plan was, that Windows programs could be executed on OS/2 as well. Well, Microsoft decided to "backstab" OS/2, by rolling their own professional grade OS, based on the NT kernel. But this meant, that for development you wanted developers to be able to link against system DLLs, without having all the different variants of the DLL available. Instead a dynamic linkage "template" would have been used for creating both the DLL and the executables (both being in the PE format), which are these particular .lib files, which are not libraries at all, but merely symbol and ordinal tables (this is a little known fact, but PE binary symbols can be loaded not only by a string identifier, but also by a integer number, the so called ordinal).

    A side effect of ordinals is, that they allow to hide the human readable symbols, so that you could make use of the DLL only if you knew the ordinal ←→ function relationship.

    In Unix the tradition was, "you build it on the system you're going to run it on", or "you have all the target system files in place". So there was never an incentive so separate library and linkage information. Technically the same would work for DLLs, too. PEs can export a symbol and relocation table, which DLLs do, and a linker could grab all the information it requires from that, just fine.

    If you were to hide symbols with Unix shared objects, you'd normally do this by using a single struct with all the function pointers in it, and only exporting a global constant instance of this struct by name, which contains a lot of not explicitly named pointers. You could do exactly the same with Windows DLLs, though.

    TL;DR: The reason for this is not a technical one, but a marketing and distribution decision one.

    0 讨论(0)
  • 2021-01-31 18:33

    In Windows, the client program does not need to link with a static library in order to access functions in a DLL. The dynamic linking can happen entirely at run time without the client program even being aware of the existence of the DLL at the time it was compiled.

    For example, if you wanted to call a function name "foo" in a DLL named "bar.dll", you could write code like this:

    HINSTANCE hinst = LoadLibrary("bar.dll");
    FARPROC foo = GetProcAddress(hinst, "foo");
    foo();
    

    And "foo" and "bar.dll" could easily have been values that were only established at run time, say via a configuration file or some other user input.

    The purpose of the static library is to automate this dynamic loading process, by creating stubs that appear like to be regular functions as far as the client program is concerned, but are linked to the DLL at runtime. Typically this linking happens at the time the client process is loaded, but libraries can also be generated that will load and link on demand, so the DLL won't be brought into memory until it is actually needed. It is the static library that determines when the linking occurs.

    For the most part, a compiler can generate these libraries automatically, so technically they aren't needed when just linking to DLL functions. However, the one exception to this (that I'm aware of) is when linking to shared variables.

    In a Windows DLL you can create a shared data segment with variables that can be accessed by any process that has loaded that DLL. The information about the size and types of those variables is stored in the associated static library, and can't be determined from the DLL alone. In order to access those variables, the client program must link against the static library for that DLL.

    As far as I'm aware, Linux Shared Libraries don't support such a concept.

    Update

    I should also mention that on Windows it's possible to create a DLL where the function entry points are only exported by ordinal (number) rather than name. This can be thought of as a form of data hiding and will typically be used when an implementor wants certain functions to remain private.

    Someone with access to the static library would be able to call those functions by name, since the library would have the details linking the function name to the appropriate ordinal. Anyone who only had the DLL would have to manually link to the functions by ordinal or generate their own static library with made up names.

    0 讨论(0)
提交回复
热议问题