Libraries in Linux: static and dynamic.
- To fully understand what the Libraries in Linux are about, we are going to do an overview from the most general topic to the most specific one.
First of all, what is a library?
A library is a set of pre-compiled code blocks called functions. The library contains a variety of functions, which together form a large package called: library. For example, could a collection of logical operations. e.g. logical.h
Why we use them?
We use libraries in general because we can go even further from sharing code inside one process, we can also share code between completely different programs, and we can reuse that code for future programs and provide access to some aspects of hardware/software.
In over all, we also can say that a library is a collection of object files which can be linked with binaries statically or dynamically.
That means that when it comes to libraries on Linux operating system we have two basis concepts: static and dynamic.
- Static libraries are bound to a program statically at a compile time. Here a program is linked with the shared library and the kernel loads the library (in case it is not in memory) upon execution.
- Dynamic or shared libraries: are loaded when a program is launched and loaded into memory and binding occurs at run time. Dynamic or shared libraries can further be categorized into:
- Dynamically linked libraries – here a program is linked with the shared library and the kernel loads the library (in case it is not in memory) upon execution.
- Dynamically loaded libraries – the program takes full control by calling functions with the library.
Knowing that, we can now explore how do they work, the libraries contain the object code of many programs that allow you to do common things, such as reading the keyboard, writing on the screen, handling numbers, performing mathematical functions, and so on.
How to create and to use them
- A static library is a library that is "copied" into our program when we compile it. Once we have the executable of our program, the library is useless (in other words, it is used for other future projects). We could delete it and our program would continue working, since it has a copy of everything it needs. Only that part of the library that is needed is copied. For example, if the library has two functions and our program only calls one, only that function is copied.
Once we have our code, to get a static library we must perform the following steps:
Get the object files (.o) from all our sources (.c). For this they are compiled with
$ gcc -c source.c -o source.o.
The -c option tells the compiler not to create an executable, but just an object file.
Create the library (.a). For this, the ar command is used with the following parameters:
$ ar -rv libname.a source1.o source2.o ...
The -r option tells the ar command that it has to insert (or replace if they are already inside) the files object in the library. The -v option is "verbose", so it displays information while it is doing all that it has to be done. Next we put all the object files that we need.
We already have the library. Now, when compiling our program with the compile (gcc for all of this examples), we must tell it where the libraries are and what they are. The compilation order would be:
$ gcc -o myprogram myprogram.c -I<path1> -I<path2> ... -L<path1> -L<path2> ... -llibrery1 -llibrery2
The -I<path> are to indicate where are the header files neccessary for compilation (of the program and those of our libraries). The -L<path> are to indicate the directories in which the libraries are located. The -llibrery are to indicate that this library should be taken. In the command we only put "library". The lib prefix and the .a extension are automatically set by the compiler.
Important tips: when compiling, the libraries are read consecutively and only loaded from each of them what is necessary.
- In the other hand, a dynamic library is not copied into our program when compiling it. When we have our executable and we are executing it, every time the code needs something from the library, it will look for it. If we delete the library, our program will give an error that it cannot be found.
Saying that and following the previous example in the static library, now we have:
To compile the same file, but with a dynamic library, we have to follow the next steps:
Compile the source files, as before, to obtain the object files.
Create the library with the ld command. The options for this command would be
$ ld -o liblibrery.so object1.o object2.o ... -shared
The option -o liblibrary.so indicates the name we want to give to the library. The -shared option tell you to make a library and not an executable. And object1.o ... are the object files that we want to put into the dynamic library.
Once the executable is compile, we need one last step. We have to tell the program, while is running, where the dynamic libraries are, since it will look for them every time a function is called. We have to define the environment variable LD_LIBRARY_PATH, in which we put all the directories where the dynamic librares of interest are located, this is highly important.
$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<path1>:<path2>:<path3> $ export LD_LIBRARY_PATH
Now that we know what the libraries are and how to use them, let have a look at the differences between them and the advantages of each:
What are the differences between static and dynamic libraries?
1. The extension
- .a: static, traditional libraries. Applications link to these libraries of object code.
- .so: dynamically linked shared object libraries. These libraries can either be linked in at runtime but statically aware or loaded during execution by the dynamic link loader.
2. The large
- A program compiled with static libraries is larger, than a dynamic, since everything it needs is copied.
3. Portability
- A program compiled with the static libraries can be taken to another computer without having to bring up the libraries.
4. Speed of execution
- A program compiled with static libraries is, in principle, faster in execution. When you call a library function, you have it in your code and you don't have to go read the dynamic library file to find the function and execute it.
5. Other differences
If we change a static library, the executables are not affected. If we change a dynamic, the executables are affected. For example:
What are the advantages and drawbacks of each of them?
Static Libraries:
✔️ Faster because a set of commonly used object files is put into a single library executable file which enables you to build multiple executables without the need to recompile the file.
✔️ Changes made to the files and program require relinking and recompilation.
✔️ No dependencies
❗ Higher memory usage, as the OS can no longer use a shared copy of the library.
❗ If the library needs to be updated, your application/program needs to be rebuilt.
Dynamic libraries:
✔️ Consumes disk space and memory only once.
✔️ If a .so is already loaded, the executable may load faster because it is a smaller file
✔️ Multiple running applications use the same library without the need of each file having its own copy.
❗ If a .so is not already loaded, the executable’s remaining undefined symbols must be resolved at start-up.
❗ There is a chance to break executables without relinking.
Finally, which one do we choose? To answer this question, it would be necessary to review the characteristics of the needs of the program/app. For programs that are not very large and for simplicity, people recommend using Static Libraries. While, the Dynamic Libraries are recommended for huge programs or for system libraries, since they are on all Linux computers, it is not necessary to carry them from one machine to another.
By: Lilibeth Tabares.