Linux allows dynamic linking of libraries during the time the executable is loaded or when required (shared libraries are usually of .so.x.y.z)
The shared object can be created using the steps mentioned in [3].
Suppose the shared library is named libmylib.so
If you create an executable using the shared object while compilation of the executable
gcc source.c –lmylib –o myapp
In this case when myapp is loaded/started the shared object mylib is loaded.This is the very basic method of using a shared library.
There is a way to load/unload the dl libraries as needed using the dlopen,dlclose routines
Use –ldl while linking and include dlfcn.h in the executable
The related functions are
dlopen()
The dlopen function opens a library and prepares it for use.
void * dlopen(const char *filename, int flag);
If filename an absolute path, dlopen() will just try to use it .Otherwise, dlopen() will search for the library in the following order:
*List of directories in the user's LD_LIBRARY_PATH environment variable.
*The list of libraries specified in /etc/ld.so.cache (which is generated from /etc/ld.so.conf).
/lib, followed by /usr/lib
Note the order here; this is the reverse of the order used by the old a.out
loader. The old a.out loader, when loading a program, first searched /usr/lib, then /lib .This shouldn't normally matter, since a library should only be in one or the otherdirectory (never both)
the value of flag must be either
RTLD_LAZY, meaning ``resolve undefined symbols as code
from the dynamic library is executed'', or
RTLD_NOW, meaning ``resolve all undefined symbols before dlopen() returns and fail if this cannot be done''.
RTLD_GLOBAL may be optionally or'ed with either value inflag, meaning that the external symbols defined in the library will be made available to subsequently loaded libraries
If the libraries depend on each other (e.g., X depends on Y), then you need to load the dependees first (in this example, load Y first, and then X).
dlerror()
Errors can be reported by calling dlerror(), which returns a string describing the error from the last call todlopen(), dlsym(), or dlclose(). One oddity is that after calling dlerror(), future calls to dlerror() will return NULL until another error has been encountered.
dlsym()
dlsym() looks up the value of a symbol in a given (opened) library.
void * dlsym(void *handle, char *symbol);
the handle is the value returned from dlopen, and symbol is a NULL-terminated string.
dlclose()
The converse of dlopen() is dlclose(), which closes a DL library. The dl library maintains link counts for dynamic file handles, so a dynamic library is not actually deallocated until dlclose has been called on it as many times as dlopen has succeeded on it.
This is an example i came across from which i learnt how to use the above functions
#include "stdio.h"
#include "stdlib.h"
#include "dlfcn.h"
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
printf ("%f\n", (*cosine)(2.0));
dlclose(handle);
}
The program should be compiled linking dl
gcc -o foo foo.c -ldl
Library constructor and destructor functions
Libraries should export initialization and cleanup routines using the gcc
__attribute__((constructor)) and
__attribute__((destructor)) function attributes.
Constructor routines are executed before dlopen returns (or before main() is started if the library is loaded at load time).
Destructor routines are executed before dlclose returns (or after exit() or completion of main() if the library is loaded at load time).
The C example prototypes for these functions are:
void __attribute__ ((constructor)) my_init(void);
void __attribute__ ((destructor)) my_fini(void);
Shared libraries must not be compiled with the gcc arguments ``-nostartfiles'' or ``-nostdlib''. If those arguments are used, the constructor/destructor routines will not be executed
Related commands:
ldd
Displays a list of the shared libraries each program requires. For example if your executable is a.out and you need to know what all libraries this a.out requires for operation you can invoke the command ldd as ldd a.out
In Linux, the environment variable LD_LIBRARY_PATH is a colon-separated set of directories where libraries should be searched for first, before the standard set of directories
Or it can be added in the configuration file /etc/ld.so.conf
ldconfig
creates the necessary links and cache (for use by the run-time linker, ld.so) to the most recent shared libraries found in the directories specified on the command line, in the file /etc/ld.so.conf, and in the trusted directories (/usr/lib and /lib). ldconfig checks the header and file names of the libraries it encounters when determining which versions should have their links updated. ldconfig ignores symbolic links when scanning for libraries.ldconfig should normally be run by the super-user as it may require write permission on some root owned directories and files. It is normally run automatically at bootup, from /etc/rc, or manually whenever new DLL's are installed.
nm :
The nm command can report the list of symbols in a given library. It works on both static and shared libraries. For a given library it lists the symbol names defined, each symbol's value, and the symbol's type. It can also identify where the symbol was defined in the source code (by filename and line number), if that information is available in the library (see the -l option).
The type is displayed as a letter lowercase means that the symbol is local, while uppercase means that the symbol is global (external). Typical symbol types include T (a normal definition in the code section), D (initialized data section), B (uninitialized data section), U (undefined; the symbol is used by the library but not defined by the library), and W (weak; if another library also defines this symbol, that definition overrides this one).
Related links/references:
[1]http://www.linuxjournal.com/article/6463
[2]http://www.linuxjournal.com/article/1059
[3]http://www-106.ibm.com/developerworks/linux/library/l-shobj/