Getting started with Linux library file writing [from chinaunix]

Source: Internet
Author: User

 

From: http://hi.baidu.com/harrybobo/blog/item/ae3347b51711afc637d3ca69.html

 

I. Why should I use library files?
We will certainly encounter this situation in actual programming: There are several projects with the same function modules,
The implementation code is also the same, which is what we call repeated code. For example, many projects have a user verification function.
The code snippet is as follows:
// Userlogin. h file, providing function declaration
Int isvaliduser (char * username, int namelen );
// The userlogin. c file to verify user information
Int isvaliduser (char * username, int namelen)
{
Int isvalid = 0;
/* The following is the specific processing code, skipped */
Return isvalid
}
If each project stores the two userlogin. h and userlogin. c files, there are several drawbacks:
1. duplicate modules exist in each project, resulting in code duplication.
2. code reusability is poor. Once the isvaliduser code changes, we need to manually modify the userlogin of other projects to maintain design consistency. c files are time-consuming, laborious, and error-prone.
Library files are an organizational form of public code.
In order to solve the above two drawbacks, a solution is proposed to store public code in library files. The main point is to put public (that is, it can be reused multiple times) the target code is separated from the project and stored in the library file. When the project uses the code, it can obtain the target code from the library file during compilation or running. There are two types of library files: static library and dynamic library.


Ii. Static and Dynamic Databases
If the program loads the library file during compilation, the static library is used. If the target code is loaded at runtime, it becomes a dynamic library. In other words, if a static library is used, the static library code is copied to the code segment of the program during compilation, and the size of the program expands. If a dynamic library is used, only the name and function name of the library file are retained in the program, and the library file and function body are searched during runtime. The size of the program remains unchanged.
The principle of static databases is to change the space for time to increase the program volume and reduce the running time;
The dynamic library is "Time for Space", which increases the running time, but reduces the size of the program itself.
The following is an example of how to use these two libraries.

Iii. Writing and using static databases
1. Overview
The extension of the static library file is generally. A, which is easy to write.
(1) Compile Function Code
(2) compile and generate target files
(3) archive the target file with an AR file to generate a static library file.
Note that the archive file name must start with Lib.
Usage tips:
(1) Add the path of the static library header file after the-I parameter of GCC.
(2) Add the directory of the library file after the-l parameter of GCC
(3) Add the library file name after the-l parameter of GCC, But remove the lib and. A extensions.
For example, if the library file name is libtest. A, the parameter is-l test.
2. Write the simplest static library file
Write the following two files and place them in the same directory.
Myalib. h // static library header file
Myalib. C // static library implementation file
// Myalib. h file content
Void test ();
// Myalib. c file content
# Inlcude
Void test ()
{
Printf ("test/N ");
}
3. Create a library file
(1) generate the target file
Gcc-C myalib. c
A myalib. o file is generated after execution.
(2) Use the AR command for archiving. The format is Ar-RC.
Again, the archive file name must start with lib and end with..
Ar-RC libtest. A myalib. o
A libtest. A file is generated after execution.
4. Use library files
(1) Compile a Test Program Main. C. The content is
// Main. C test the program called by the static library
# Include "myalib. H" // include the function header file. Otherwise, an error is reported during compilation.
Int main (INT argc, char * argv [])
{
Test ();
Return 0;
}
(2) Compile the target file. Add the path of the static library header file to the-I parameter.
Gcc-I/root/exercise-O main. O-C main. c
A main. o file is generated.
(3) generate an executable file. Add the path of the static library file to the-l parameter,
Add the library file name (excluding the hitting lib and ending. a) to the end of the-l parameter. As shown below
Gcc-O main-L/root/exercise main. O-ltest
An executable file named main is generated.
In addition, note that the-l parameter should be added to the end of the input file name; otherwise, an error is returned.
For example, GCC-O main-L/root/exercise-ltest main. O will prompt
Main. O (. Text + 0x11): In function 'main ':
: Undefined reference to 'test'
Collect2: LD returned 1 exit status
The reason is unknown :-)
(4) display the executable file
Run./main and Output
Test
The execution is successful.

4. Writing dynamic libraries
1. Overview
A dynamic library generally ends with. So, which means shared object.
The basic generation steps are as follows:
(1) Compile Function Code
(2) compile and generate dynamic library files with the-shared and-FPIC options,
The library file name starts with lib and ends with. So.

There are two usage methods: [B] [/B] [B] implicit call and display call [/B]
Implicit calling is similar to static library usage, but you need to modify the configuration file/etc/lD. So. conf of the dynamic link library;
The system functions such as dlopen, dlsym, dlerror, and dlclose are used in the main program.
The specific call method is described in "5. Dynamic library call.
2. Write the simplest dynamic library file
For easy comparison, we still use files in the static library as an example.
Write the following two files and place them in the same directory.
Myalib. h // static library header file
Myalib. C // static library implementation file

// Myalib. h file content
Void test ();
// Myalib. c file content
# Inlcude
Void test ()
{
Printf ("test/N ");
}
3. compile and generate a dynamic library. The library file name starts with lib and ends with. So.
Gcc-FPIC-shared-O libtest. So myalib. c
A libtest. So file is generated.

5. implicit call of a dynamic library
The implicit call means that the library file name does not appear in the code, that is, the code and
The code for calling the static library is similar.
1. Compile the test file
// Main. C test the program implicitly called by the dynamic library
# Include "myalib. H" // include the function header file. Otherwise, an error is reported during compilation.
Int main (INT argc, char * argv [])
{
Test ();
Return 0;
}
2. Compile the test program. Similar to the static library, add the path of the header file to the-I parameter.
Gcc-I/root/exercise-O main. O-C main. c
A main. o file is generated.
3. Generate a test program
Gcc-O main-L/root/exercise main. O-ltest
A main file is generated.
4. Execute the test program
./Main
The prompt is displayed.
./Main: Error while loading shared libraries: libtest. So: cannot open shared object file: no such file or directory.
This is because the path of the dynamic library is not known when the program runs, so it cannot be found.
There are three solutions to this problem. See the following section.

6. Three Methods to share the dynamic library with the System
(Note again: this section references the article "Linux dynamic link library advanced application" by Computer World Network Yu Yiqi"
Address
[Url = Response
)
(1) copy the dynamic link library to the system shared directory or use the dynamic link library under the system shared directory.
Establish a connection (either a hard connection or a symbolic connection). The system shared directory,
The Directory of Linux dynamic link inventory, including
/Lib,/usr/lib, and a series of directories listed in the/etc/lD. So. conf file.
Instance: Run
# Cp libtest. So/lib
# Ldconfig
Or:
# Ln-s 'pwd'/libtest. So/lib
# Ldconfig
Note that there are two backticks before and after PWD to obtain the output of the PWD command, that is, the current directory.
Then execute main.
(2) append the Directory Name of the Dynamic Link Library to the configuration file/etc/lD. So. conf of the dynamic link library.
# PWD>/etc/lD. So. conf
# Ldconfig
Then execute main.
(3) use the dynamic link library management command ldconfig to force it to search for a specified directory and update the cache file to facilitate dynamic loading.
# Ldconfig 'pwd'
Then execute main.
Note that the third method is effective, but the effect is temporary for program testing. Once ldconfig is run again, the content of the cached file may change, the required dynamic link library may not be shared by the system. in addition, either way, the essence is to use the ldconfig command to add the path of the dynamic library file to the system library list (the first two permanent, the third temporary)
Ldconfig is a dynamic link library management command
To share the dynamic link library with the system, you also need to run the dynamic link library management command-ldconfig
The ldconfig command is mainly used in the default search directory (/lib and/usr/lib) and dynamic library configuration file/etc/lD. so. find the shared dynamic link library under the directory listed in conf (format as described earlier, lib *. so *) to create a dynamic loader (LD. so) the required connection and cache file. the default cached file is/etc/lD. so. cache. This file stores the list of Dynamic Linked Library names in the sorted order.
Ldconfig is usually run when the system starts. When you install a new dynamic link library, you need to manually run this command.
The ldconfig command line is used as follows:
Ldconfig [-v | -- verbose] [-N] [-N] [-x] [-F conf] [-C cache] [-r root] [-L] [-p | -- print-Cache] [-C format] [-- format = format] [-V] [-? | -- Help | -- usage] path...
The options available in ldconfig are described as follows:
(1)-V or -- verbose: When this option is used, ldconfig displays the directory being scanned, The searched dynamic link library, and the name of the connection it created.
(2)-N: When this option is used, ldconfig only scans the directory specified by the command line and does not scan the default directory (/lib,/usr/lib ), nor scan the configuration file/etc/lD. so. conf directory.
(3)-N: This option indicates that ldconfig does not recreate the cache file (/etc/lD. So. cache). If the-x option is not used, ldconfig updates the file connection as usual.
(4)-X: This option indicates that ldconfig does not update the file connection. If the-n option is not used, the cached file will be updated normally.
(5)-f conf: This option specifies that the configuration file of the dynamic link library is Conf, and the default value is/etc/lD. So. conf.
(6)-C cache: This option specifies that the generated cache file is cache. The default value is/etc/lD. so. cache. This file stores the list of dynamically linked libraries that can be shared in the sorted order.
(7)-R root: This option changes the root directory of the application to root (implemented by calling the chroot function ). when this option is selected, the system default configuration file/etc/lD. so. conf, which corresponds to root/etc/lD. so. conf. for example, when-r/usr/ZZZ is used, open the configuration file/etc/lD. so. in Conf,/usr/ZZZ/etc/LD is actually enabled. so. CONF file. this option can greatly increase the flexibility of dynamic link library management.
(8)-L: Generally, ldconfig automatically establishes a connection to the dynamic link library when searching for a dynamic link library. when this option is selected, the expert mode is enabled. You need to manually set the connection. this option is not required for general users.
(9)-P or -- print-Cache: This option indicates that ldconfig prints the names of all the shared libraries saved in the current cache file.
(10)-C format or -- format = format: This option is used to specify the format used by the cache file. There are three types: LD (old format), new (new format) and compat (compatible format, which is the default format ).
(11)-V: This option prints the version information of ldconfig and then exits.
(12 )-? Or -- help or -- Usage: the three options share the same role, so that ldconfig prints the help information and then exits.

7. explicit call of dynamic Databases
Explicit calling means that the library file name appears in the code, and you need
Open and manage library files. The main points are:
(1) include the [B] dlfcn. H [/B] system header file
(2) Use the dlopen function to open the library file and specify the open mode.
The first parameter of dllope is the name of the shared library, and the specified shared library will be searched in the following location.
① Environment variable LD_LIBRARY_PATH lists all directories separated by semicolons.
② The list of databases found in the file/etc/lD. So. cache is refreshed by the ldconfig command.
③ Directory usr/lib.
④ Directory/lib.
⑤ Current directory.
The second parameter is how to open the shared library. There are two values
① Rtld_now: load all functions in the shared library to the memory.
② Rtld_lazy: pushes back the function loading operation in the shared library until a function is loaded when dlsym () is called.
(3) Use the dlerror () function to test whether the function is successfully opened and handle the error;
(4) use dlsym to obtain the function address and store it in a function pointer.
Then, use the obtained function pointer to call the function.
When the ghost program ends, use dlclose to close the opened dynamic library to prevent resource leakage.
⑺ Use the ldconfig tool to add the dynamic library path to the system library list.
1. Compile the test file
// Main. C test the program explicitly called by the dynamic library
# Include // system header file used for dynamic Library Management
# Include "myalib. H" // include the function header file. Otherwise, an error is reported during compilation.
Int main (INT argc, char * argv [])
{
// Declare the function pointer of the corresponding function
Void (* Ptest )();

// Load the dynamic library
Void * pdlhandle = dlopen ("libtest. So", rtld_lazy );

// Handle errors
If (pdlhandle = NULL ){
Printf ("failed Load Library/N ");
Return-1;
}
Char * pszerr = dlerror ();
If (pszerr! = NULL)
{
Printf ("% s/n", pszerr );
Return-1;
}

// Obtain the function address
Ptest = dlsym (pdlhandle, "test ");
Pszerr = dlerror ();
If (pszerr! = NULL)
{
Printf ("% s/n", pszerr );
Dlclose (pdlhandle );
Return-1;
}

// Implement function call
(* Ptest )();
// Close the dynamic library when the program ends
Dlclose (pdlhandle );
Return 0;
}
2. Compile the test file and use the-LDL option to specify that the generated object module must use the shared library.
Gcc-O main-LDL main. c
A main file is generated after execution.
3. Execute the test program
Run./main
Output
Test
It indicates the operation is successful.

8. Other issues that should be paid attention to when using dynamic libraries
1. Whether it is an explicit or implicit call to a dynamic library, you must use
The ldconfig tool adds the path of the dynamic library to the system library list. Otherwise, an error occurs during running.
2. You can use the LDD command to check which shared libraries are used by the program.
The usage of the LDD command line is as follows:
LDD [-- version] [-v | -- verbose] [-d | -- Data-relocs] [-r | -- function-relocs] [-- help] file...
The options are described as follows:
(1) -- version: This option is used to print the version number of LDD.
(2)-V or -- verbose: This option instructs LDD to output as detailed as possible about the dependent Dynamic Link Library.
(3)-D or -- Data-relocs: This option is relocated and displays non-existent functions.
(4)-R or -- function-relocs: This option executes data object and function relocation, and reports non-existing objects.
(5) -- help: This option is used to print the help information of LDD.
We generally use the-V option.
Now let's look at several instances.
(1) results of static database connection
# LDD main
Libc. so.6 =>/lib/tls/libc. so.6 (0xb74ad000)
/Lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0xb75eb000)
It can be seen that when a static library is used, the Library has been compiled into a part of the program, so LDD output is only used.
System Library.
(2) result of implicit connection with a dynamic database
Libtest. So =>/root/exercise/libtest. So (0xb75e2000)
Libc. so.6 =>/lib/tls/libc. so.6 (0xb74ab000)
/Lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0xb75eb000)
It can be seen that when dynamic libraries are implicitly used, all the dynamic libraries (including the system and user) used will be displayed.
(3) results of dynamic library explicit connection
LDD main
Libdl. so.2 =>/lib/libdl. so.2 (0xb75e1000)
Libc. so.6 =>/lib/tls/libc. so.6 (0xb74aa000)
/Lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0xb75eb000)
It can be seen that when a dynamic library is explicitly used, the program no longer saves the information for opening the dynamic library during running, and only retains the information of the system library used.
This is similar to the output when a static library is used.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.