Linux System Programming: Creating and Using Dynamic Libraries

Click the above“Mechanical and Electronic Engineering Technology” to follow us
In Linux system programming, a dynamic library (Dynamic Library) is also known as a shared library (Shared Library), which is a library that is loaded only when the program runs. Dynamic libraries can be shared by multiple programs, saving memory and disk space, and making it easier to update the code in the library without recompiling all programs that use it. Dynamic libraries typically have a .so file suffix.

Creating Dynamic Libraries

Compile the source file into Position Independent Code (PIC): Use the -fPIC or -fpic option to compile the source file, generating object files.
gcc -fPIC -c source_file.c
The code generated by -fPIC can be loaded at any location in memory, while the code generated by -fpic may bind addresses faster on certain architectures but may not be suitable for all platforms.
Creating the dynamic library: Use the gcc with the -shared option to specify generating a dynamic library.
gcc -shared -o liblibrary_name.so object_file1.o object_file2.o ...
Here, the -shared option tells the compiler to generate a dynamic library.
Setting version numbers: Typically, dynamic libraries have a major version and a minor version. These version numbers can be included in the library file name.
gcc -shared -o liblibrary_name.so.1.0 object_file1.o object_file2.o ...
ln -s liblibrary_name.so.1.0 liblibrary_name.so.1
ln -s liblibrary_name.so.1 liblibrary_name.so
Here, liblibrary_name.so.1.0 is the library file with a specific version number, while liblibrary_name.so.1 and liblibrary_name.so are symbolic links pointing to the major version and the current version of the library, respectively.

Using Dynamic Libraries

Linking at compile time: When compiling the program, use the -L option to specify the path of the dynamic library, and use the -l option to specify the library to link.
gcc program.c -L/path/to/library -llibrary_name -o program
The compiler will use the symbols in the library file to resolve the symbol references in the program.
Setting runtime library paths: Ensure that the dynamic linker can find the dynamic library. You can specify the library search path by setting the LD_LIBRARY_PATH environment variable.
export LD_LIBRARY_PATH=/path/to/library:$LD_LIBRARY_PATH
Or, you can add the library path to the system-level library cache using the ldconfig command.
sudo ldconfig /path/to/library
Run the program: You can now run the compiled program, and the dynamic linker will load the required dynamic libraries at program startup.

Notes

  • Dynamic libraries are loaded at runtime, so the executable file size is smaller compared to using static libraries.

  • Dynamic libraries allow the code in the library to be shared in memory, meaning that all programs using the same dynamic library share the same code, saving memory.

  • Updating dynamic libraries only requires replacing the library file without recompiling the programs that use the library.

  • The use of dynamic libraries increases program dependencies; if the library file is deleted or moved, the program may not run.

  • Version management of dynamic libraries is important; incompatible library updates may cause programs that depend on them to crash.

A Simple Example:

Assume we have a simple math library that provides two functions: add and multiply.
Writing source code: First, we create two source files add.c and multiply.c.

add.c:

int add(int a, int b) {    return a + b;}

multiply.c:

int multiply(int a, int b) {    return a * b;}
Compile the source files into a shared object: Use gcc to compile these source files and use the -shared option to generate a shared object (dynamic library).
gcc -fPIC -shared -o libmath.so add.c multiply.c
Here, -fPIC generates position-independent code, -shared specifies generating a dynamic library, and libmath.so is the name of the dynamic library we created.
Setting version numbers (optional): To better manage the version of the dynamic library, we can set version numbers.
mv libmath.so libmath.so.1
ln -s libmath.so.1 libmath.so
Here, libmath.so.1 is the library file with a specific version number, while libmath.so is a symbolic link pointing to the current version.
Now, we create a program main.c that uses our math library.
Writing the program using the library: main.c uses the add and multiply functions.

main.c:

#include <stdio.h>
extern int add(int, int);
extern int multiply(int, int);
int main() {    int sum = add(3, 4);    int product = multiply(3, 4);
    printf("Sum: %d\n", sum);    printf("Product: %d\n", product);
    return 0;}
Compiling the program: When compiling main.c, we need to specify the path and name of the dynamic library. However, since the dynamic library is loaded at runtime, we only need to declare the external functions during compilation.
gcc main.c -o program -L. -lmath
  • -L. specifies the search path for the dynamic library (current directory).

  • -lmath specifies the library to link; the linker will look for libmath.so or libmath.so.1.

Setting runtime library paths: Before running the program, ensure that the dynamic linker can find the dynamic library. You can specify the library search path by setting the LD_LIBRARY_PATH environment variable.

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
Run the program: After compilation, you can run the generated program.
./program
The output should be:

Sum: 7
Product: 12
If everything is set correctly, the program will run successfully and dynamically load the libmath.so dynamic library at runtime.
Linux System Programming: Creating and Using Dynamic Libraries

Want to learn more

Scan the code to follow

Leave a Comment