Dynamic link library in C

I have some questions about dynamic link libraries in C.

Q1. enter image description here

My textbooks uses a picture to illustrate how DLL works, and it seems that some relocation and symbol table information of libvector.so and libc.so are copied (the arrow is attached to their side), but whenever the assembler encounters a reference to an object whose ultimate location is unknown, it generates a relocation entry that tells the linker how to modify the reference when it merges the object file into an executable. For libc.so, everything is known(it has all definitions), so there shouldn't be any relocation entry for libc.so, isn't it

Q2. My textbook says that:

"a single copy of the .text section of a shared library in memory can be shared by different running processes",

Let's say I have a program that uses printf. Does the .text section of printf stay in RAM forever or does it get evicted from RAM when the first program finishes, and get loaded in RAM when a second process uses printf again? If the latter is the case, isn't that very inefficient that the .text section of printf gets evicted and loaded in RAM many many times since we have multiple processes that could be running in the background?

1 answer

  • answered 2018-11-08 01:03 landru27

    Q1: The diagram you provided seems correct to me. It is main2 that is being constructed; the relocation and symbol table information of libvector.so and libc.so are being copied in so that the final executable can make use of them. From the perspective of main2, functions, constants, etc. from libc and libvector are being added, so I agree with your textbook that the relocation and symbol table information of libvector.so and libc.so are being copied.

    Q2: You present only the two extremes: "stay in RAM forever" or "evicted from RAM when the first program finished". Almost certainly, the sharable portions of libraries will stay in RAM as long as some recently-running process has made use of them. A typical strategy an OS will use is an LRU algorithm to evict 'unused' things from RAM, but only when it wants to load more into RAM than there is room for. So, on a lightly used machine, nearly everything might hang around in RAM for quite a long time; but on a very heavily overtaxed machine, the OS will be constantly discarding things from RAM that it will need again very soon. But even then, some things are used so frequently, they are unlikely to ever meet the LRU threshold, so you might have some certain things in RAM for a long time, even if most things are being evicted.

    Q1 follow-up: In answer to your question in your comment: correct: there is nothing in main2.c to define functions found in libc. It is because of this that the linker needs to copy in the relocation and symbol table information for printf() from libc.so, so that when main2 is executed, libc.so also gets loaded.

    In more detail:

    printf() might be called from main2.c, but printf() is declared in stdio.h and defined in e.g. printf.c [1] and compiled into libc.so; main2.c can be compiled because the compiler can see the signature for printf() (in stdio.h), but to build main2 (the executable), the code already compiled in libc.so needs to be linked with main2.o (the intermediate object file). ld does this by copying in the references that cause execution of main2 to dynamically load libc.so. [2]

    [1] Compilers will differ on how standard library functions are defined; gcc has a file printf.c which defines printf() (and it's actually a pass-through to vfprintf()); other compilers might do it differently -- but the whole point of libraries is that you don't ever need to look at the definition of printf() and other library functions; you only need the declaration from the appropriate .h file in order to know how to call it in your own .c file.

    [2] Or, if you build a statically linked executable, the code -- not just the symbol table -- is copied from the library file into the executable being built, and that executable can be run even on a machine without the .so files present. Whether or not dynamic linking or static linking is better for building a given executable depends on several factors.