Don't be nervous. Shared Objects have nothing to do with object-oriented technology! We are now discussing the dynamic link library on the Linux platform (similar to the DLL in Windows ). We have used some types of libraries in different periods during the encoding process to call simple functions (such as Cprintf()
) Or complex functions (such as C ++sort()
). Library makes daily programming easier and allows developers to focus on the tasks at hand. Imagine how tedious it is to write printf () and file I/O functions for every piece of code you have written!
Almost every software build relies heavily on libraries that allow the software to complete different tasks-from printing to the screen to logging on to the network. Some libraries are provided by the system, and some libraries are compiled by third-party vendors or users themselves. During compilation, these libraries are linked to the application. If the application uses a lot of libraries and has linked all the code, the application will become astonishing. This is why the "Shared Library" is used. It does not link to the application source code, but is dynamically installed as the application needs.
Compilation process
Before building a shared object, you must first understand the compilation process and what the shared object is. As shown below, we use the famous and historical Hello world code example.
Listing 1: Hello. C; shared object defined
#include "stdio.h"void main(){ printf("Hello World!"); } |
Use the following command line to compile the program:
This command createsHello. The compiler can now perform the following steps:
- Syntax check: Check the syntax and syntax of the file.
- Compile: Compile the file to generate the target file of the Code. In the generated target file, the unresolved function name is marked, as shown in figure
printf()
. (See the following file format .)
- Link: Call an independent program called a linked program. (In UNIX, the program is
ld
.) The linked program tries to parse functions and variables by searching for the code in different libraries. For example,printf()
Code resident in a filelibc.a
(Orlibc.so
. If you do not need a standard library, you must specify it.
The preceding commands for compiling and linking code can be divided into the following two commands:
>$ gcc -c hello.c $ ld -lc -o hello hello.c |
This is the compilation step (-c
Option ). Step 2 is the link, useld
Programs generate executable Hello programs.
File Format
Elf representativeExecutable and link format. This format is used for most UNIX objects including Linux objects. There are three basic types of target files:
- Relocation files have code and data linked to other target files to create executable files, share target files, or relocate another target.
- The executable file has programs to be executed.
- The shared target file has code and data linked to other shared targets or relocated files. (Shows the target file format .)
Each file has an elf header file that resides at the beginning of the file. It acts as a road sign for other files. Section represents the smallest unit that can be processed in a file. It contains information for some links. The section header file table contains the section information in the file. The program header file table (if any) tells you how to create a process image. If the target file is an executable file, the image must be used.exec
The program uses the program header file table to generate a sub-process. Note that the location of the elf header file remains unchanged. The location of other parts may be different from that shown in the figure.
file
The program uses the EFL header file (see utilities and tools described later in this article) to print information about the file. (LibelfThe library package provides program interfaces for accessing information in the EFL header file .)
This link is calledStatic Link. When static compilation is used, the code in the library is merged with the application (which makes the executable file very large ). Any valuable application uses hundreds of functions provided as the library. Some of these libraries are standard, some are third-party, and some are internal. When static compilation is used, the final Executable File becomes very large, and all the Code must be loaded into the memory at runtime. no matter whether the function is used or not, the code is put into the memory.
If there is a mechanism: the Library can dynamically load the memory as needed, which can reduce the space occupied by the program in the memory, or divide the program into several small parts, which is too good. This is also easy to distribute, install, and update. This mechanism exists. These dynamic link libraries are named like this (DLL in windows and shared object in Linux ). Use their applications as dynamic executable files.
Back to Top
Naming Conventions
Before discussing shared objects, let's take a brief look at the naming rules of the database. The static library is generally composed of letters.LibAnd has.. The shared object has two different names:SonameAndReal name.SonameContains the prefix "lib", followed by the Library name, followed by ". So" (followed by another dot), and a number indicating the main version number. Soname can be limited by the path information of the prefix. Real name is the real file name that contains the compiled code of the library. Real name adds a dot, a small number, another dot, and a release number after the soname. (The release number and the corresponding dot are optional .)
We will seeProgram-library how-The name of the definition, calledLinker nameIt refers to a soname without a version number. The database name used by the customer is the linker name. Generally, this is the link to linket name. The soname is the link to the real name.
Take soname here/usr/lib/libhello.so.1
As an example. This is a fully qualified soname, which is linked/usr/lib/libhello.so.1.5
. The corresponding linker name is/usr/lib/libhello.so
. There seems to be many names to manage, but there are tools to help you manage them. (For more information, seeldconfig
.)
Now let's take a look at the substantive content and write a sample sharing object. The Library's soname islibprint.so.1
, Real name islibprint.so.1.0
. The library hasprintstring(char*)
It will print the word "string:", followed by any string passed to it as a parameter.
Back to Top
Write a shared library
For the library to be used, there are two basic files that must be written. The first is the header file, which declares all the functions exported from the library, and the client in the Code includes these functions. The second is the definition of the function to be compiled and put as a shared object. For our example, the header file is similar:
Listing 2: libprint. H code; header file
/* file libprint.h - for example use! */void printstring(char* str); |
The library code is very basic and displayed in the next list.
Listing 3: libprint. C code
/* file libprint.c */#include "stdio.h" void printstring(char* str) printf("String: %s/n", str); } |
There are two special functions,_init(void)
And_fini(void)
. When loading data to the database, the dynamic loader automatically calls these two functions. The default implementations of these two functions are provided, but you can ignore them and write your own functions. We add these two functions to the libprint. C code to print the diagnostic interruption information when calling them.
Listing 4: Code of _ Init () and _ Fini ()
void _init(){ printf("Inside _init()/n"); } void _fini(){ printf("Inside _fini()/n"); } |
Now we merge it with the code in listing 3. It's easy, isn't it? To compile a custom library, you must uselibprint.c
Andlibprint.h
And then write the corresponding functions. Now let's continue writing this library.
Back to Top
Compile the Shared Library
The following commands compile the Library:
$ gcc -fPIC -c libprint.c $ ld -shared -soname libprint.so.1 -o libprint.so.1.0 -lc libprint.o |
Note: In the GCC command line-fPIC
. This is generatedPosition-independent codeRequired. The command is translated to generate code that can be loaded anywhere in the process space of the process. This is very important for shared objects. Use this option to minimize the number of relocations required. Once the shared object used by the executable program is loaded, some space must be allocated to it. Some locations must be assigned to the text and data departments. If they are not built in a "location-independent" manner, a large number of migrations are required for the program to load shared objects, which affects the performance.
Now let's analyze it and send itld
.-shared
Indicates that the output file is considered a shared library. Pass-soname name
Specifies what the soname is.-o name
Specifies the real name of the shared object. It is important to specify soname and real name, because they are used during library installation.
Back to Top
Install and use a shared library
Now that you have built a library, install it now and let a small client program use it. To install the shared library, useldconfig
This special program. Typically, shared libraries are installed on/usr/lib
,lib
Or/usr/local/lib
Directory. Once a library is created, it will be copied to one of these directories. Then, runldconfig
Program.
Ldconfig
$ldconfig -v -n ....: libprint.so.1 => ./libprint.so.1.0 |
Now you have createdlibprint.so.1.0
Namelibprint.so.1
. The next step in installation is to create another link with the Link name, as shown below:
Link of The Link name
$ ln -sf libprint.so libprint.so.1 |
To/usr/lib
,lib
Or/usr/local/lib
To copy files in the directory, you need the superuser permission. When the application is running, these directories are automatically searched to parse the database. If you do not have the superuser permission, the shared library can be installed in any directory, but you need to set environment variables before running the program that uses this library. This environment variableLD_LIBRARY_PATH
You must set the path to the location of the shared library. As an example, if the shared library is in the same directory as the executable program, it can be as follows:
LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH |
Now we have completed the settings required for compilation and the shared libraries that have just been built for execution. It is easy to use a shared library. :)
Listing 5: client. C; sample customers who use the printstring () function in the library
#include "libstring.h" void main()} printf("In Main!/n"); printstring("In Main!"); } |
Run the following command to compile the program into an executable program:
$ gcc -o client client.c -L. -lprint |
This generatesClientWhich assumes that the library and code are in the same directory (-L. -lprint
). Once executed, the following output is generated:
$ client Inside _init() In Main! String: In Main! Inside _fini() $ |
Now that we have created a shared library, install it and use it! Let's study its internal mechanism and observe when executingClient. When the program is started, the system identifies that the program depends on the dynamic library. Therefore, the system calls the loader,/lib/ld-linux.so.X
(X is the version number) to load the required database. Availableldd
To determine the library on which the executable file depends.
LDD
$ ldd client libprint.so.1 => ./libprint.so.1 libc.so.6 => /lib/libc.so.6 /lib/ld-linux.so.2=> /lib/ld-linux.so.2 |
This shows the library on which the file client is dependent. Then the loader loads these databases and calls the corresponding_init()
. The loader firstLD_LIBRARY_PATH
Find the database in the path recorded by the environment variable, and then/etc/ld.so.conf
Search for the record in the standard path. If the database cannot be found, an error is returned. Under normal circumstances, the loader loads the library and execution files required by the program. All of these are transparent and carried out behind the screen.
Back to Top
Utilities and tools
Let's take a brief look at the file, nm, and objdump tools, which are very useful binary utilities.
The file program can be used to find the file type. The detected file can be a text file (for example, libprint. c), an executable file (for example, client), or data (for example,/dev/hda5 ). File is useful in viewing the platform for compiling a specific file, whether it is executable, and other things. Run the following command:
File
$ file clientclient: ELF 32-bit LSB executable, Intel 80386, version 1, dynamically linked(uses shared libs), not stripped |
NM lists all symbols in an object. (For objects, we generally refer to object files or libraries .) Pass an object through nm to display the function names used or exported by the object, the parts of the object, symbols, and object types. The symbol can be undefined or external, or global or some other identifiers. Inlibprint.so
Run onnm
To generate the following output:
Nm
$ nm libprint.so00001490 A _DYNAMIC00001480 A _GLOBAL_OFFSET_TABLE00001510 A __bss_start00001510 A _edata00001510 A _end00000452 A _etext00000400 T _fini000003d8 T _init000003d8 t gcc2_compiled U printf@@GLIBC_2.000000428 T printstring |
Objdump displays information about object files, which can be specified in the command. The option passed to objdump controls the information displayed. If you want to carefully view the details inside the object file, these are good utilities.
Okay. I hope you are interested in sharing objects. Don't go away. A lot more!
References
- For more information, see the original article on the developerworks global site.
- On the Linux documentation project home page, you can find things about Linux.
- Review the file man page, which contains the file command (version 3.27) document.
- Objdump man page is a document about the objdump command.
- Libelf man page is a document about the libelf command.
- David A. Wheeler, author of Program-library howto, discusses how to use and create libraries on Linux.
- See the building shared objects on Sun Solaris tutorial.
- There are some general concepts on Dynamic Linking in "AIX version 4.3 general programming concepts.
- Please refer to quick reference on shared objects for a good reference.
- Here is a brief description of Introduction to building dynamic libraries on different platforms.
About the author
Ashish Bansal has a bachelor's degree in electronics and communication engineering from the College of Technology at Banaras Hindu University in wanana, India. He is currently a software engineer at sapient. You can contact him through the abansal@ieee.org.
The opinions expressed in this article are irrelevant to those expressed by sapient.