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系统下的两种库(静态库和动态库),此外对这两种库进行了特点的说明以及通过编写代码实现了两类库的应用。

相关推荐
友友马13 分钟前
『 Linux 』网络层 - IP协议(一)
linux·网络·tcp/ip
茶猫_1 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展
A.A呐2 小时前
【Linux第一章】Linux介绍与指令
linux
Gui林2 小时前
【GL004】Linux
linux
ö Constancy2 小时前
Linux 使用gdb调试core文件
linux·c语言·vim
lb36363636362 小时前
介绍一下strncmp(c基础)
c语言·知识点
tang_vincent2 小时前
linux下的spi开发与框架源码分析
linux
xiaozhiwise2 小时前
Linux ASLR
linux
wellnw2 小时前
[linux] linux c实现共享内存读写操作
linux·c语言
a_安徒生2 小时前
linux安装TDengine
linux·数据库·tdengine