Dynamic libraries

Dynamic libraries

  • Why using libraries in general

When we are coding, regularly we have the necessity of make calls of functions, functions that you are writing, or functions that are pre established in libraries of certain programming languages, like printf() in C. If you needs that the compiler understand your code when you want to print on the standard output with "printf()", your code should include:

#include <stdio.h>

Printf() function are declared and related macros are defined in “stdio. h” which is a header file, that it is called exactly like a library in C language.

For Static Libraries, step by step to create it:

gcc -Wall -pedantic -Werror -Wextra -c *.c

(With the gcc compiler, create objects file(s) (.o)


ar -rc libholbertonschool.a *.o

(With 'ar' command you pass the .o file(s))


ranlib libholbertonschool.a

(generates an index to the contents of an archive and stores it
in the archive.)


ar -t libholbertonschool.a

(list the object file(s) inside the static library)



gcc main.c -L. -lholbertonschool -o alpha

-L flag tells to the complier that the follow argument is the library

Next we see how to create the dynamic libraries.

  • How do they work

The Work with dynamic libraries, makes your code flexible to edit some function or bunch of functions, that your program needs to run, after of it had been compiled. That, is because the library object code is not injected on your compiled and linked object code. On your linked object code will be the memory address of your object code library.

Dynamic linking links the libraries at the run-time. Thus, all the functions are in a special place in memory space, and every program can access them, without having multiple copies of them. That, makes that the dynamic library is a shared library.

No hay texto alternativo para esta imagen
  • How to create them (Linux only)

First, you need to create or declare your function, or bunch of functions on .c files. Then, you need to compile your file, suitable for inclusion in a library.

gcc -fPIC -c <file_name>.c

linkjavier@ubuntu:~$ gcc -fPIC -c file_name.c

Or type *.c if you want to compile all .c files of the working directory.

linkjavier@ubuntu:~$ gcc -fPIC -c *.c

If your code is compiled with -fPIC, it is suitable for inclusion in a library - the library must be able to be relocated from its preferred location in memory to another address, there could be another already loaded library at the address your library prefers.

Then, compile with the object file and obtain the shared library:

linkjavier@ubuntu:~$ gcc -shared -o library_name.so file.o

Or type *.o if you want to compile all object files of the working directory.

linkjavier@ubuntu:~$ gcc -shared -o library_name.so *.o

  • How to use them (Linux only)

You can generate an executable file, and run every time that you needs. You can edit functions on your shared library, and then run your program again. No needs to compile your entire program again.

A good way to understand the usability of libraries on UNIX based system is know how about the OS manage it:

What LD_LIBRARY_PATH and LD_PRELOAD do.

LD_LIBRARY_PATH is an environment variable you set to give the run-time shared library loader (ld.so) an extra set of directories to look for when searching for shared libraries. Multiple directories can be listed, separated with a colon (:). This list is prepended to the existing list of compiled-in loader paths for a given executable, and any system default loader paths. The programs ld.so find and load the shared objects (shared libraries) needed by a program, prepare the program to run, and then run it.

With LD_PRELOAD, we can preload shared libraries on our system. Let's make an excersise of call a popular function called random() that it's included in a popular header file. Then, we will create another random() function, but to probe the PRELOAD command, the fake_random function, always return the same number.

In this way:

Let's create a function with the usage of the known and popular function rand() to return a different random number in every call. Random() is preestablished in stdlib.h

random_num.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
int main(){
  srand(time(NULL));
  printf("%d\n",rand()%1000);
  return 0;
}

We can see that the function random() returns everytime differents numbers:

linkjavier@Ubuntu:~$ gcc random_num.c -o a.out
linkjavier@Ubuntu:~$ ./a.out
513
linkjavier@Ubuntu:~$ ./a.out
941
linkjavier@Ubuntu:~$ ./a.out
366
linkjavier@Ubuntu:~$ 

Then, let's create a fake random function called rand() in the file fakerand.c: (This function, always return the same value)

fakerand.c

int rand(){
    return 10; 
}

Create a dynamic library with the fakerand.c file, and then, preload the library in your system with LD_PRELOAD.

gcc -shared -fPIC fakerand.c -o fakelib.so
export LD_PRELOAD=~/fakelib.so

Now, with the fake rand() function that it is included on the loaded shared library fakelib.so, the program random_num.c returns our custom random number 10.

linkjavier@ubuntu:~$ gcc random_num.c -o a.out
linkjavier@ubuntu:~$ ./a.out 
10

linkjavier@ubuntu:~$ ./a.out
10
linkjavier@ubuntu:~$ ./a.out
10
linkjavier@ubuntu:~$

Now, we can type a command lld that show us the libs that the program uses:

linkjavier@Javier-ThinkPad-E470:~$ ldd -v random_num.out 
	linux-vdso.so.1 (0x00007ffd64159000)
	/home/linkjavier/fakelib.so (0x00007fc0278a5000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc0274b4000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fc027ca9000)


	Version information:
	./random_num.out:
		libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
	/lib/x86_64-linux-gnu/libc.so.6:
		ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
		ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2

ldconfig

We know that ld-linux.so is responsible for loading the dynamic libraries which a program needs to run, this is where ldconfig enters the scene. The ldconfig utility scans the directories where the dynamic libraries are commonly found (/lib and /usr/lib)  and creates both symbolic links to these libraries and a cache (stored on /etc/ld.so.cache) containing their locations so that ld-linux.so can quickly find them whenever necessary. This is done when you run ldconfig without any arguments (you can also add the -v option to see the scanned directories and the created symbolic links):

You can list the contents of the created cache with the -p option:

ldconfig -p


  • What are the differences between static and dynamic libraries

The object code of your static library are included on your compiled program. You need to edit your static library, and compile the entire program again to include your changes.

Shared library are linked dynamically simply including the address of the library. It means, that you can replaced the library for a new one.

  • What are the advantages and drawbacks of each of them

A shared library can provide after selling support for newer hardware of software updates.

Programs written in different programming languages can call the same shared library functions as long as the programs follow the same callings convention that the function uses.

要查看或添加评论,请登录

Javier Charria Gómez的更多文章

  • Static Library

    Static Library

    Why use libraries When we are programming, mostly we need to declare functions that helps you to complete tasks in a…

  • What happens when you type $ gcc main.c

    What happens when you type $ gcc main.c

    The compile process has diferrent subprocess: Preprocesing: Receives the code and preparate it to next pompiling…

社区洞察

其他会员也浏览了