Linux文件IO(5):静态库和动态库的使用

目录

[1. 库的概念](#1. 库的概念)

[2. 静态库](#2. 静态库)

[2.1 静态库的特点](#2.1 静态库的特点)

[2.2 静态库的创建](#2.2 静态库的创建)

[2.2.1 编写函数](#2.2.1 编写函数)

[2.2.2 编译生成目标文件](#2.2.2 编译生成目标文件)

[2.2.3 创建静态库](#2.2.3 创建静态库)

[2.2.4 查看库中符号信息](#2.2.4 查看库中符号信息)

[2.3 链接静态库](#2.3 链接静态库)

[2.3.1 编写应用程序](#2.3.1 编写应用程序)

[2.3.2 编译并链接静态库](#2.3.2 编译并链接静态库)

[2.3.3 执行应用程序](#2.3.3 执行应用程序)

[3. 动态库](#3. 动态库)

[3.1 动态库的特点](#3.1 动态库的特点)

[3.2 动态库的创建](#3.2 动态库的创建)

[3.2.1 编写函数](#3.2.1 编写函数)

[3.2.2 编译生成目标文件](#3.2.2 编译生成目标文件)

[3.2.3 创建共享库](#3.2.3 创建共享库)

[3.2.4 为共享库文件创建链接文件](#3.2.4 为共享库文件创建链接文件)

[3.2.5 编写应用程序](#3.2.5 编写应用程序)

[3.2.6 编译并链接共享库](#3.2.6 编译并链接共享库)

[3.2.7 执行程序](#3.2.7 执行程序)

[3.2.8 添加共享库的加载路径](#3.2.8 添加共享库的加载路径)

[3.2.9 查看可执行文件所使用的动态库](#3.2.9 查看可执行文件所使用的动态库)

[4. 总结](#4. 总结)


1. 库的概念

库是一个二进制文件,包含的代码可被程序调用,常见的库有标准C库、数学库、线程库......

库有源码,可下载后编译;也可以直接安装二进制包。

库是事先编译好的,可以复用的代码。在OS上运行的程序基本上都要使用库。使用库可以提高开发效率。

注:Windows和Linux下库文件的格式不兼容

Linux下包含静态库和动态库两种。

2. 静态库

2.1 静态库的特点

  • 编译(链接)时把静态库中相关代码复制到可执行文件
  • 程序中已包含代码,运行时不再需要静态库
  • 程序运行时无需加载库,运行速度更快
  • 占用更多磁盘和内存空间
  • 静态库升级后,程序需要重新编译链接

2.2 静态库的创建

2.2.1 编写函数

编写一个hello函数,去打印"hello world"。

cpp 复制代码
#include <stdio.h>

int hello()
{
	printf("hello world\n");
	return 0;
}

2.2.2 编译生成目标文件

bash 复制代码
gcc  -c  hello.c  -Wall

2.2.3 创建静态库

bash 复制代码
ar  -rsv  libhello.a  hello.o

注意:

1 静态库名字要以lib开头,后缀名为.a

2 没有main函数的.c 文件不能生成可执行文件。

ar参数:

|---|-----------------------------|
| c | 禁止在创建库时产生的正常消息 |
| r | 如果指定的文件已经存在于库中,则替换它 |
| s | 无论 ar 命令是否修改了库内容都强制重新生成库符号表 |
| v | 将建立新库的详细的逐个文件的描述写至标准输出 |
| q | 将指定的文件添加到库的末尾 |
| t | 将库的目录写至标准输出 |

2.2.4 查看库中符号信息

bash 复制代码
nm -a libhello.a

nm:显示指定文件中的符号信息

-a 显示所有符号

2.3 链接静态库

2.3.1 编写应用程序

cpp 复制代码
#include <stdio.h>

void hello();

int main(int argc,char* argv[])
{
	hello();
	return 0;
}

2.3.2 编译并链接静态库

bash 复制代码
gcc -o test test.c -L. -lhello

-L 表示库所在的路径

-l 后面跟库的名称

2.3.3 执行应用程序

bash 复制代码
./test 

可以看到应用程序已成功链接了我们编写的静态库,并执行打印了hello world。

3. 动态库

3.1 动态库的特点

  • 编译(链接)时仅记录用到哪个动态库中的哪个符号,不复制动态库中相关代码
  • 程序不包含库中代码,尺寸小
  • 多个程序可共享同一个库
  • 程序运行时需要加载库
  • 库升级方便,无需重新编译程序
  • 使用更加广泛

3.2 动态库的创建

3.2.1 编写函数

编写一个hello函数,去打印"hello world"。

cpp 复制代码
#include <stdio.h>

void hello()
{
	printf("hello world\n");
}

编写一个bye函数,去打印"bye"。

cpp 复制代码
#include <stdio.h>

void bye()
{
	printf("bye\n");
}

3.2.2 编译生成目标文件

cpp 复制代码
gcc -c -fPIC hello.c bye.c -Wall

3.2.3 创建共享库

bash 复制代码
gcc -shared -o libcommon.so.1 hello.o bye.o

3.2.4 为共享库文件创建链接文件

bash 复制代码
ln -s libcommon.so.1 libcommon.so

符号链接文件命名规则:lib<库名>.so

3.2.5 编写应用程序

cpp 复制代码
#include  <stdio.h>
#include "common.h"  
int main() 
{
    hello();
    bye();
    return  0;
}

3.2.6 编译并链接共享库

bash 复制代码
gcc -o test test.c -L. -lcommon

3.2.7 执行程序

bash 复制代码
./test

可以看到存在报错提示,

含义:可执行文件所使用的动态库找不到

解决办法:

  • 把库拷贝到/usr/lib和/lib目录下
  • 在LD_LIBRARY_PATH环境变量中添加库所在路径
  • 添加/etc/ld.so.conf.d/*.conf文件,执行ldconfig刷新

3.2.8 添加共享库的加载路径

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

再去执行应用程序

bash 复制代码
​./test

3.2.9 查看可执行文件所使用的动态库

bash 复制代码
ldd 你的可执行文件

4. 总结

本文介绍了库的概念,并介绍了linux系统下的两种库(静态库和动态库),此外对这两种库进行了特点的说明以及通过编写代码实现了两类库的应用。

相关推荐
Kisorge31 分钟前
【C语言】指针数组、数组指针、函数指针、指针函数、函数指针数组、回调函数
c语言·开发语言
gywl1 小时前
openEuler VM虚拟机操作(期末考试)
linux·服务器·网络·windows·http·centos
日记跟新中3 小时前
Ubuntu20.04 修改root密码
linux·运维·服务器
码农君莫笑3 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
BUG 4043 小时前
Linux——Shell
linux·运维·服务器
大霞上仙4 小时前
Linux 多命令执行
linux·运维·服务器
晨欣4 小时前
Kibana:LINUX_X86_64 和 DEB_X86_64两种可选下载方式的区别
linux·运维·服务器
AI青年志4 小时前
【服务器】linux服务器管理员查看用户使用内存情况
linux·运维·服务器
爱吃西瓜的小菜鸡4 小时前
【C语言】判断回文
c语言·学习·算法
dessler5 小时前
Docker-run命令详细讲解
linux·运维·后端·docker