Linux中的动态库与静态库

软链接与硬链接

软链接

当我们不在本地路径下运行时,运行目标二进制文件一般要写明该程序路径.
在这里插入图片描述
但是这样运行对于路径较为复杂的程序极为耗费时间,为了简便操作,我们可以将该可执行程序的路径设置为软链接.此时的软链接一般也可认为是windows可执行程序的快捷方式.

创建软链接命令如下:

[yzh@VM-4-5-centos ~]$ ln -s /home/yzh/my.exe mysoft

在这里插入图片描述
注意:
创建软链接不能将可执行程序的路径写错了,不然运行该程序会出错.

硬链接

硬链接指在指定的目录下,建立文件名与目标inode文件的映射关系,一般默认为"取别名".

创建硬链接命令如下:

[yzh@VM-4-5-centos ~]$ ln /home/yzh/my.exe myhard

在这里插入图片描述

硬链接的用途

我们知道,inode中还有一个引用计数,它代表文件名与目标文件关联的个数.

  • 当我们创建一个硬链接,代表多了一个文件名与目标文件相关联,引用计数+1.
  • 当我们删除一个硬链接,代表少了一个文件名与目标文件相关联,引用计数-1.
  • 当引用计数减少为0时,代表没有文件名与目标文件相关联,进而代表该文件被真正删除.

删除链接关系命令:

[yzh@VM-4-5-centos ~]$ unlink myhard

在这里插入图片描述

延申问题

当我们创建一个空目录时,为什么该文件的引用计数为2呢?
在这里插入图片描述
因为自身的目录名与自身内部的 " . " ,都和同一个文件的inode具有映射关系.其中" . " 也代表着当前目录(也就是我们所在的目录).
在这里插入图片描述
再比如: 当我们在ceshi目录内创建一个ceshi1目录,进入该目录,使用ll -ail 目录查看,发现 该目录下的 "…“与ceshi目录的inode相同,说明”…"与ceshi目录也建立了映射关系.其中 "…"也代表着上一级目录.

在这里插入图片描述
所以,我们可以通过目标目录的引用计数-2(自身对应关系以及下一级目录下的 “.”),来判断该目录中所存在的下一级目录个数了(也代表着下一级目录中"…"的个数).

软硬来链接的区别

当我们查看创建的软硬链接,区别如下:

  • 软链接有独立的inode,说明软链接是一个独立的文件.
  • 硬链接没有独立的inode,说明硬链接不是一个独立的文件.
    在这里插入图片描述

动态库与静态库

为了便于理解,我们创建了两个源文件与两个头文件,这些文件只为用以动静态库的相关操作.

mymath.c

累加到目标值.

#include "mymath.h"                                                                                            
int addToTarget( int form,int to )
 {
    
    
           int sum = 0;
 
           for( int i = form; i <= to; ++i )
            {
    
    
              sum += i;
            }
            return sum;
 }

mymath.h

 #pragma once
 #incldue <stdio.h>
 extern int addToTarget( int from, int to );

myprint.c

打印所给字符串以及时间戳.

#include "myprint.h"
void Print( const char* str )
{
    
    
   print("%s[%d]\n",str,(int)time(NULL));
}

myprint.h

#pragma once
#include <time.h>
extern void Print( const char* str);

main.c

调用myprint以及mymath相关库.

#include "myprint.h"                                                                                                #include "mymath.h"
int main()
  {
    
    
    Print("hello world\n");
    int res = addToTarget(1,100);
    printf("%d\n",res);
    return 0; 
 }

静态库

生成静态库

1.将所有源文件生成二进制文件.(不可执行).
在这里插入图片描述

2.使用rc命令,将这些二进制文件统一打包为静态库.

  • -r(replace): 如果创建的目标文件与静态库文件名相同,则将新的静态库文件替换掉重名的静态库文件.
  • -c(create): 创建静态库.
    在这里插入图片描述
    3:将静态库中头文件与静态库统一放在指定目录中.
    在这里插入图片描述

当然,为了简便以上操作,我们也可以采用使用Makefile统一生成.
在这里插入图片描述
使用make,makeoutput命令同意生成并打包静态库.
在这里插入图片描述

静态库的使用

方法一: 利用sudo cp命令分别将头文件复制在: /usr/include ,静态库文件复制: /lib64.
在这里插入图片描述
但是使用gcc命令编译链接成打可执行程序时,需要指明编译的库.(库名去点前后缀即可) 例如: libhello.a --> hello.
在这里插入图片描述
方法二:直接指明头文件,静态库文件的路径,并让编译器在指定路径下搜索.
编译命令如下:

gcc main.c -I ./output/include/ -L ./output/lib -lhello
  • -I: 表示指明头文件搜索路径.
  • -L: 表示指明库文件搜索路径
    在这里插入图片描述

动态库

动态库的生成

方法一:

第一步:先将源文件统一编译为二进制文件(不可执行).

gcc -fPIC -c mymath.c -o mymath.o -std=c99
gcc -fPIC -c myprint.c -o myprint.o -std=c99

在这里插入图片描述
第二步: 使用gcc -shared命令所有目标文件打包生成动态库库

gcc -shared myprint.o mymath.o -o libhello.so

在这里插入图片描述

第三步: 将头文件与静态库统一放在指定目录中

我们选择将.h头文件放在output目录下的include中,将动态库.so文件放在include目录下的lib目录中.
在这里插入图片描述
方法二: 使用Makefile统一打包生成.

我们将打包生成动静态库的所有命令写入Makefile中,使用Makefile命令统生成动静态库.
在这里插入图片描述
在这里插入图片描述

动态库的使用

与动态库的使用不同的是,我们使用gcc -I -L -l编译链接产生的可执行程序不可以直接运行.
在这里插入图片描述
原因:我们在gcc 使用 -I -L 表明动态库的路径时,是对gcc编译器说的,当我们要运行加载程序的时候,此时已经生成了可执行程序,跟gcc没有任何关系,但是要运行时,进程需要通过->虚拟地址空间->页表映射去寻找动态库的位置,所以我们要对Linux系统表明动态库的位置.,静态库不需要将库的地址告诉操作系统是因为静态库在加载的时候已经将代码加载到内存中了,不需要再去与操作系统建立映射关系查找.

方法一: 增加环境变量

由于LD_LIBRARY_PATH是进程运行动态库时所要搜索的路径,我们需要将动态库的路径添加到LD_LIBRARY_PATH环境变量即可.

在LD_LIBRARY_PATH 环境变量中使用export加动态库的绝对路径,使用达echo命令查看环境变量是否成功添加.

[yzh@VM-4-5-centos userlib]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/yzh/userlib/output.lib

在这里插入图片描述

方法二: 配置 /etc/ld.so.conf,d/ 文件

第一步: 在/etc/ld.so.conf,d/目录中创建一个文件(后缀一定要是.conf)

[yzh@VM-4-5-centos userlib]$ sudo vim /etc/ld.so.conf.d/yzh.conf

在这里插入图片描述
在该文件中加入动态库的路径.
在这里插入图片描述
之后再使用 sudo ldconfig命令将/etc/ld.so.conf.d/下的目录文件更新就可以了.
在这里插入图片描述
方法三: 设置软连接

将动态库的路径设置为路径为 /lib64/下的软链接,在设置软硬接中最好表明的是动态库的绝对路径,否则系统系统会找不到动态库。

[yzh@VM-4-5-centos userlib]$ sudo ln -s /home/yzh/userlib/output/lib/libhello.so /lib64/libhello.so

在这里插入图片描述
此时,我们使用 ls /lib64 查看软链接是否建立.
在这里插入图片描述

动静态库的区别

  • 静态库使用时是将可执行程序加载到内存中后通过页表映射到地址空间的代码区中,并且每一个进程运行该程序都会将该程序反复加载到内存中,极大浪费了内存空间.

  • 动态库可以和可执行程序进行分批加载,当进程运行到可执行程序中的动态库时,进程会将动态库加载到内存中,内存通过页表进行映射到地址空间中栈堆之间的共享区,当进程执行到动态库时,会从代码区跳转到共享区执行,当有多个进程时运行该可执行程序的动态库时,此时加载到内存中的动态库共享到每个进程,所以动态库也称为共享库.
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_63300413/article/details/131754814