[软件设计/软件工程] 静态库和动态库详解(部分参考他人)

[复制链接]
发表于 2022-5-2 13:17:16
静态库和动态库的区别

1.静态函数库

    这类库的名称一般为 libxxx.a;使用静态函数库编译出来的文件比较大,因为整个函数库的所有数据都会集成到目标代码中,它的优势很明显,就是编译出来的可执行程序不需要外部库支持,因为所有用到的函数都已经编译进去了。当然这也是一个缺点,因为如果静态库发生变化,那么你的程序必须重新编译。

2.动态函数库

    这类库的名称一般为 libxxx.so;与静态函数库相比,动态函数库在编译时并不编译成目标代码,只有当你的程序执行相关函数时才会调用函数库中对应的函数。 ,所以动态函数库生成的可执行文件比较小。由于函数库不是集成到你的程序中,而是在程序运行时动态应用和调用的,所以程序运行环境中必须提供相应的库。动态函数库的变化不会影响你的程序,所以升级动态函数库更方便。
Linux系统有几个重要的目录来存放相应的函数库,如/lib /usr/lib。

动态库制作

示例说明:

假设当前目录有以下文件:
/main.c//#include<math2.h>头文件是我自己的

  1 #include<stdio.h>

  2 #include<math2.h>

  3 int main(){
  4         int i=11,j=22;

  5         printf("__%d__\n",myadd(i,j));

  6         return 0;

  7 }



math2.h///     

  1 #ifndef _MATH2_H_

  2         #define _MATH2_H_

  3         int myadd(int ,int );

  4 #endif



/myadd.c//                                      

  1 int myadd(int i,int j){
  2         return i+j;

  3 }
对于头文件,这里使用两种情况:

案例1:放在/usr/include/

案例2:编译时使用-I指定需要使用头文件的目录



动态库制作使用:

现在我想让 myadd.c 成为一个动态库,以便 main.c 可以使用动态库

第一步:gcc -c myadd.c -o myadd.o -fpic

//使用fpic参数的原因:myadd.o需要制作一个库文件,这个库文件和一般的不一样

二进制文件,他需要一些特殊的格式和特殊的信息,所以使用-fpic来生成这些特殊的

特殊格式和信息



第 2 步:gcc -shared -WL,-soname,libmath.so.1 -o libmath-1.0.0.so

myadd.o

//-shared 表示生成动态库; -wl,-sonname,libmyadd.so.1 会导致单词

字符串 libmyadd.so.1 记录为最终生成的库文件 libmath-1.0.0.so 中的文件名

.



ok 至此,动态库已经生成,但是此时还不能使用。需要完成以下工作:

使用动态库有两种情况:



案例一:放入系统库

第一步:cp libmath-1.0.0.so /lib/

注意此时使用的库名是math;



第二步:但是此时通过gcc main.c -lmath还是不能编译成功,这是因为编译器

在系统库中找库,是直接找libmath.so,而不是libmath-1.0.0.so,所以需要

在 /lib/ 下为 libmath-1.0.0.so 创建一个软链接:

ln -s /lib/libmath-1.0.0.so libmath.so



第三步:gcc编译出来的文件还是不能执行,这是因为,我们在做动态库的时候

指定链接的库名是 libmath.so.1(但我们真正的库是 libmath-1.0.0.so),因为

而且我们还需要创建一个关于 libmath-1.0.0.so 的软链接:

ln -s /lib/libmath-1.0.0.so libmath.so.1

完成以上工作后,我们就可以在我们的应用程序中完全使用创建好的动态库了,也就是编译

可以翻译运行



案例2:可以把头文件、生成的库、关于库的两个软链接放到当前(或

在您指定的目录中);

第一步:生成案例2中提到的文件,并一个一个的放到当前目录下

第二步:这时候编译需要用到:

gcc main.c -L。 -一世。

//for -L 用于指定编译时需要使用库搜索路径 //for -I 用于指定

编译时存放头文件的目录

第三步:编译成功后,文件还是不能直接运行,需要添加环境变量指定

链接库时的搜索路径(注意不要写错变量名):

    export LD_LIBRARY_PATH=/hyg/linux高级编程/文件IO/景泰



之后就可以在自己设置的目录下运行自己生成的动态库文件了。





静态库的制作:

案例一:放入系统库



第 1 步:gcc -c myadd.c -o myadd.o

第 2 步:ar rc libmyadd.a myadd.o

//第二步,制作静态库

第 3 步:cp libmyadd.a /lib/

第 4 步:gcc mian.c -lmyadd -I。 -静止的



情况2:可以放在指定目录下,编译时需要指定路径,方法同动态库的情况2
显式调用动态库

    显式调用动态库需要四个函数的支持,函数dlopen打开动态库,函数dlsym获取动态库中对象的基地址,函数dlerror获取显式动态库操作中的错误信息, 函数 doclose 关闭动态库。
[bill@billstone make_lib]$ cat main.c

#include <dlfcn.h>

int main()

{

                void *pHandle;

                void (*pFunc)();                                                    //  指向函数的指针

                int *p;

                pHandle = dlopen("./d1.so", RTLD_NOW);                  //  打开动态库

                if(!pHandle){

                                printf("Can't find d1.so \n");

                                exit(1);

                }

                pFunc = (void (*)())dlsym(pHandle, "print");                //  获取库函数 print 的地址

                if(pFunc)

                                pFunc();

                else

                                printf("Can't find function print\n");

                p = (int *)dlsym(pHandle, "p");                                      //  获取库变量 p 的地址

                if(p)

                                printf("p = %d\n", *p);

                else

                                printf("Can't find int p\n");

                dlclose(pHandle);                                                                //  关闭动态库

                return 0;

}

[bill@billstone make_lib]$ gcc -o tds main.c –ld1 –L.
这时候./tds不能马上使用,因为在使用动态函数库的时候,会搜索/usr/lib和/lib目录下的动态函数库,而我们此时生成的库不在它。这时候有几种方法可以让它运行成功: 最直接最简单的方法就是把libstr_out.so拉到/usr/lib或者/lib。还有一种方法是导出LD_LIBRARY_PATH=$(pwd) 另外可以把我们生成的库的目录添加到/etc/ld.so.conf文件中,然后/sbin/ldconfig。 /etc/ld.so.conf 是一个非常重要的目录,里面存放着链接器和加载器在搜索共享库时要检查的目录。默认是从/usr/lib/lib中读取的,所以我想顺利运行,我们也可以把我们库的目录添加到这个文件中,执行/sbin/ldconfig。另外还有一个你需要了解的关于/etc/ld.so.cache的文件,里面存放了常用的动态函数库,会先加载到内存中,因为内存的访问速度要快很多比硬盘的存取速度快,因此可以提高软件加载动态函数库的速度。

查看库依赖项

使用 ldd 命令查看可执行文件所依赖的库。

此命令用于确定可执行二进制文件中包含的动态库。
[root@test root]# ldd [-vdr] [文件名]
参数说明:
--version 打印ldd的版本号
-v --verbose 打印版本信息等所有信息,包括符号
-d --data-relocs 执行符号重新部署并报告丢失的目标对象(仅适用于 ELF 格式)
-r --function-relocs 重新部署目标对象和函数,报告丢失的目标对象和函数(仅针对ELF格式)
--help 使用信息。

如果命令行中给出的库名包含“/”,则该程序的 libc5 版本将使用它作为库名;否则它将在标准位置搜索库。在当前目录中运行一个共享库,以“./”为前缀。

(The difference between static library and dynamic library
1. Static function library
The name of this kind of library is generally libxxx a; The file compiled by using the static function library is relatively large, because all the data of the whole function library will be integrated into the object code. Its advantage is obvious, that is, the compiled executable program does not need the support of the external library, because all the functions used have been compiled. Of course, this is also a disadvantage, because if the static library changes, your program must be recompiled.
2. Dynamic function library
The general name of this class library is XXX so; Compared with static function libraries, dynamic function libraries are not compiled into object code at compile time. Only when your program executes relevant functions will the corresponding functions in the function library be called, Therefore, the executable generated by the dynamic function library is relatively small. Since the function library is not integrated into your program, but is dynamically applied and called when the program is running, the corresponding library must be provided in the program running environment. Changes in the dynamic function library will not affect your program, so it is more convenient to upgrade the dynamic function library.
The Linux system has several important directories to store the corresponding function libraries, such as / lib / usr / lib.
Dynamic library making
Example description:
Assume that the current directory has the following files:
/main. c//#include<math2. h> The header file is my own
1 #include<stdio. h>
2 #include<math2. h>
3 int main(){
4         int i=11,j=22;
5         printf("__%d__\n",myadd(i,j));
6         return 0;
7 }
math2. h///     
1 #ifndef _ MATH2_ H_
2         #define _ MATH2_ H_
3         int myadd(int ,int );
4 #endif
/myadd. c//                                      
1 int myadd(int i,int j){
2         return i+j;
3 }
For header files, there are two cases:
Case 1: put it in / usr / include/
Case 2: use - I at compile time to specify the directory where the header file needs to be used
Dynamic library production and use:
Now I want myadd C becomes a dynamic library for main C can use dynamic library
Step 1: GCC - C myadd c -o myadd. o -fpic
//Reason for using FPIC parameter: myadd O need to make a library file, which is different from the general one
Binary files, it needs some special formats and special information, so - FPIC is used to generate these special files
Special formats and information
Step 2: GCC - shared - WL, - soname, libmath so. 1 -o libmath-1.0.0. so
myadd. o
//-Shared means to generate a dynamic library- wl,-sonname,libmyadd. so. 1 can lead to words
String libmyadd so. 1 is recorded as the final generated library file libmath-1.0.0 File name in so
.
OK so far, the dynamic library has been generated, but it cannot be used at this time. The following work needs to be completed:
There are two ways to use dynamic libraries:
Case 1: put it into the system library
Step 1: CP libmath-1.0.0 so /lib/
Note that the database name used at this time is math;
Step 2: but at this time, through GCC main C - lmath still can't compile successfully because of the compiler
To find a library in the system library, you can directly find libmath So instead of libmath-1.0.0 So, so you need
Libmath-1.0.0 under / lib / So create a soft link:
ln -s /lib/libmath-1.0.0. so libmath. so
Step 3: the file compiled by GCC still cannot be executed because we are making dynamic libraries
The library name of the specified link is libmath so. 1 (but our real library is libmath-1.0.0. So), because
And we also need to create one about libmath-1.0.0 Soft link of so:
ln -s /lib/libmath-1.0.0. so libmath. so. one
After completing the above work, we can fully use the created dynamic library in our application, that is, compilation
Can translate and run
Case 2: you can put the header file, the generated library and two soft links about the library into the current (or
In the directory you specify);
Step 1: generate the files mentioned in case 2 and put them in the current directory one by one
Step 2: at this time, you need to compile:
gcc main. c -L。 - I.
//For - L is used to specify the library search path to be used during compilation / / for - I is used to specify
Directory where header files are stored at compile time
Step 3: after the compilation is successful, the file still cannot be run directly. You need to add the specified environment variable
Search path when linking libraries (be careful not to write wrong variable names):
export LD_ LIBRARY_ Path = / hyg / Linux Advanced Programming / file IO / Jingtai
Then you can run the dynamic library file generated by yourself in the directory you set.
Production of static library:
Case 1: put it into the system library
Step 1: GCC - C myadd c -o myadd. o
Step 2: AR RC libmyadd a myadd. o
//The second step is to make a static library
Step 3: CP libmyadd a /lib/
Step 4: GCC Mian c -lmyadd -I。 - Static
Case 2: it can be placed in the specified directory, and the path needs to be specified during compilation. The method is the same as that of case 2 of dynamic library
Explicit call to dynamic library
Four functions are required to explicitly call the dynamic library. The function dlopen opens the dynamic library, the function dlsym obtains the base address of the object in the dynamic library, the function dlerror obtains the error information in the operation of the explicit dynamic library, and the function doclose closes the dynamic library.
[ bill@billstone  make_ lib]$ cat main. c
#include <dlfcn. h>
int main()
{
void *pHandle;
void (*pFunc)();                                                    //   Pointer to function
int *p;
pHandle = dlopen("./d1.so", RTLD_NOW);                  //   Open dynamic library
if(!pHandle){
printf("Can't find d1.so \n");
exit(1);
}
pFunc = (void (*)())dlsym(pHandle, "print");                //   Get the address of the library function print
if(pFunc)
pFunc();
else
printf("Can't find function print\n");
p = (int *)dlsym(pHandle, "p");                                      //   Get the address of Library variable p
if(p)
printf("p = %d\n", *p);
else
printf("Can't find int p\n");
dlclose(pHandle);                                                                //   Close dynamic library
return 0;
}
[ bill@billstone  make_ lib]$ gcc -o tds main. c –ld1 –L.
At this time/ TDS cannot be used immediately, because when using the dynamic function library, we will search the dynamic function library in / usr / lib and / lib directories, and the library we generated at this time is not in it. At this time, there are several ways to make it run successfully: the most direct and simplest way is to put libstr_ out. So pull to / usr / lib or / lib. Another method is to export LD_ LIBRARY_ Path = $(PWD) in addition, you can add the directory of the library we generated to / etc / LD so. Conf file, and then / SBIN / ldconfig/ etc/ld. so. Conf is a very important directory, which stores the directories that the linker and loader should check when searching for shared libraries. By default, it is read from / usr / lib / lib, so I want to run smoothly. We can also add the directory of our library to this file and execute / SBIN / ldconfig. There's another thing you need to know about / etc / LD so. Cache files, which store commonly used dynamic function libraries, will be loaded into memory first, because the access speed of memory is much faster than that of hard disk, so it can improve the speed of software loading dynamic function libraries.
View library dependencies
Use the LDD command to view the libraries on which the executable depends.
This command determines the dynamic library contained in the executable binary.
[ root@test Root]# LDD [- VDR] [filename]
Parameter Description:
--Version prints the version number of LDD
-V -- verbose print version information and other information, including symbols
-D -- data relocs performs symbol redeployment and reports missing target objects (ELF format only)
-R -- function relocs redeploys target objects and functions and reports missing target objects and functions (ELF format only)
--Help usage information.
If the library name given in the command line contains "/", the libc5 version of the program will use it as the library name; Otherwise, it will search the library in the standard location. Run a shared library in the current directory, prefixed with '. /'.
)





上一篇:SPOJ-OPTM OPTIMAL MARKS(按位建图 最小割)
下一篇:ZOJ 2760 HOW MANY SHORTEST PATH (不相交的最短路径个数)

使用道具 举报

Archiver|手机版|小黑屋|吾爱开源 |网站地图

Copyright 2011 - 2012 Lnqq.NET.All Rights Reserved( ICP备案粤ICP备14042591号-1粤ICP14042591号 )

关于本站 - 版权申明 - 侵删联系 - Ln Studio! - 广告联系

本站资源来自互联网,仅供用户测试使用,相关版权归原作者所有

快速回复 返回顶部 返回列表