《C语言杂记》静态库和动态库(Linux版)

2024-08-30 12:32

本文主要是介绍《C语言杂记》静态库和动态库(Linux版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1静态库和动态库概述

库是一种软件组件技术,库里面封装了数据和函数。库的使用可以使程序模块化。库有两种:静态库和动态库Windows系统包括静态链接库(.lib文件)和动态链接库(.dll文件)。Linux通常把库文件存放在/usr/lib或/lib目录下。Linux库文件名由:前缀lib、库名和后缀3部分组成,其中动态链接库以.so作为后缀,静态链接库通常以.a作为后缀

何为静态库和动态库?

静态库(Static library, Statically-linked library, LIB)或称静态链接库,是一个外部函数与变量的集合体。静态库的文件内容,通常包含一堆程序员自定的变量与函数,在编译期间由编译器与连接器将它集成至应用程序内,并制作成目标文件以及可以独立运作的可执行文件。而这个可执行文件与编译可执行文件的程序,都是一种程序的静态创建(static build)。其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。即静态库中的指令全部被直接包含在最终生成的可执行文件中。

动态库(Dynamic library, Dynamic-link library, DLL)或称动态链接库,是微软公司在微软视窗操作系统中实现共享函数库概念的一种实现方式。动态链接库可被多个程序同时使用。所谓动态链接,就是把一些经常会共用的代码(静态链接的OBJ程序库)制作成DLL档,当程序有需求时函数才进行链接。透过动态链接方式,存储器浪费的情形将可大幅降低。静态链接库则是直接链接到可执行文件。

一个程序编译成可执行的步骤:

在这里插入图片描述

静态库和动态库的区别在链接阶段如何处理库,如果将库链接到目标代码中则是静态库,而将库链接载入推迟到程序运行的时期则是动态库,可以实现进程之间的资源共享。




2 Linux创建和使用静态库

前面已经介绍了静态库的概念,下面我们通过一个实例来看静态库的使用。

2.1生成静态库

1)这里准备了两个库的源码st1 、st2用它们来制作库libmytest.a,如下

$ ls -l

在这里插入图片描述

$ cat st1.c

#include <stdio.h>
void print1()
{printf("Hello!I am st1!\n ");
}

$ cat st2.c

#include <stdio.h>
void print2()
{printf("Hello!I am st2!\n");
}

$ cat main.c

#include <stdio.h>
int main(int argc, const char *argv[])
{print1();print2();return 0;
}

2)生成libmytest.a文件

创建静态库用ar命令,它将很多.o转换成.a

$ gcc -c st1.c st2.c
$ ar crs libmytest.a st1.o st2.o
$ ls -l

在这里插入图片描述

$ file libmytest.a

在这里插入图片描述

静态库文件libmytest.a已经生成,用file命令查看其属性,发现它确实是归档压缩文件。用ar -t libmytest.a可以查看一个静态库包含了那些obj文件:

$ ar -t libmytest.a

在这里插入图片描述

2.2使用静态库

1.直接使用

$gcc -o test main.c libmytest.a

2.双L链接法
$gcc -o test main.c -lmytest -L.(库所在目录,.表示当前目录)

3.单L链接法(需要配置环境变量LIBRARY_PATH,把库放在所在目录配置)

$gcc -o test main.c -lmytest

前面我们已经写好了main.c,现在测试一下

$ gcc -o test main.c -L. -lmytest
$ ls -l

在这里插入图片描述

$ ./test

在这里插入图片描述

这里gcc的参数-L是告诉编译器库文件的路径是当前目录,-l是告诉编译器要使用的库的名字叫mytest。


2.3静态库总结

1.在一个头文件中声明静态库所导出的函数。
2.在一个源文件中实现静态库所导出的函数。
3.编译源文件,生成可执行代码。
4.将可执行代码所在的目标文件加入到某个静态库中,并将静态库拷贝到系统默认的存放库文件的目录下。

下面通过一个例子来说明:

源文件:mylib.c

#include <stdio.h>
void welcome(void)
{printf("welcome to libmylib\n");
}

1>编译mylib.c生成目标文件:

$gcc -o mylib.o -c mylib.c

2>将目标文件加入到静态库中:

$ar -rcs libmylib.a mylib.o

【注】库文件名以lib开头,以.a结尾。

3>将静态库copy到Linux的库目录(/usr/lib或者/lib)下:(也可以不拷贝,注意配置环境变量)

$sudo cp libmylib.a /usr/lib/libmylib.a //管理员身份

编写调用库函数的测试程序test.c:

#include <stdio.h>
int main(void)
{printf("create and use library:\n");welcome(); return 0;
}

4>使用静态库编译:

$gcc -o test test.c -lmylib

这里注意,编译时无需带上前缀和后缀。

5>运行可执行程序test:

$./test

在这里插入图片描述

在Linux下,可以使用ar命令来创建和修改静态库。

这些在linux下man ar一下就可以得到参数,这里说明几个常用的
d:从库中删除成员文件。
r:在库中加入成员文件,若存在,则替换。
c:创建一个库。
s:无论ar命令是否修改了库内容,都强制重新生成库符号表。
其他的命令用时再man。

【注】gcc -static 文件.c [-o 文件]//全部使用静态库的方法




3 Linux创建和使用动态库

动态库的基本概念
1.动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序。动态链接库是目标文件的集合,目标文件在动态链接库中的组织方式是按照特殊方式形成的。库中函数和变量的地址是相对地址,不是绝对地址,其真实地址在调用动态库的程序加载时形成。

2.动态链接库的名称有别名(soname), 真名(realname)和链接名(linker name)。别名由一个前缀lib,然后是库的名字,再加上一个后缀“.so”构成(“libxxx.so”)。真名是动态链接库真实名称,一般总是在别名的基础加上一个小版本号,发布版本等构成。除此之外,还有一个链接名,即程序链接时使用的库的名字。

3.在动态链接库安装的时候,总是复制文件到某个目录下,然后用一个软连接生成别名,在库文件进行更新的时候,仅仅更新软链接即可。

下面我们通过一个实例来学习如何生成动态库和使用动态库。

3.1生成动态库

1)当前文件夹下有下面四个文件

$ ls -l

在这里插入图片描述

文件内容分别为:

$ cat mylib.h

#ifndef _MYLIB_H_
#define _MYLIB_H_#include <stdio.h>void print1();
void print2();#endif  

$ cat dy1.c

#include "mylib.h"void print1() 
{printf("My first shared lib!\n");
}

$ cat dy2.c

#include "mylib.h" 
void print2() 
{printf("My second shared lib!\n");
}  

$ cat main.c

#include "mylib.h"  int main(int argc, char *argv[])  
{  print1();  print2();  return 0;  
}  

2)这里我们将dy1.c与dy2.c用来创建动态库

$ gcc -fPIC -Wall -c dy1.c dy2.c
$ gcc -shared -o libtest.so dy1.o dy2.o

这里 -fPIC 创建与地址无关的编译程序,-shared指定生成动态链接库。
我们也可以一步到位

$ gcc -o libtest.so -fPIC -shared dy1.c dy2.c

我们可以看到下面已经生成了一个libtest.so

$ ls -l

在这里插入图片描述

3.2使用动态链接库

在编译程序时,使用动态链接库和静态库是一致的,使用”-l库名”的方式,在生成可执行文件的时候会链接库文件。使用如下命令:

$ gcc -o test main.c -L. -ltest
$ ls -l

在这里插入图片描述

这里 -L 指定动态链接库的路劲,-ldtest链接库函数test 。-ltest是动态库的调用规则。Linux系统下的动态库命名方式是lib*.so,而在链接时表示位-l*,*是自己命名的库名。

我们可以看到这里已经生成了test可执行文件,我们可以执行一下:

$ ./test

在这里插入图片描述

可以发现发生了错误,这是因为程序运行时没有找到动态链接库造成的。程序编译时链接动态库和运行时使用动态链接库的概念是不同的,在运行时,程序链接的动态链接库需要在系统目录下才行。

这就到了动态库的路径问题,有三种方法:

1)把库拷贝到/usr/lib和/lib目录下:

$ sudo cp libtest.so /lib

【注】这里要超级用户权限sudo

我们看一下执行结果:

$ ./test

在这里插入图片描述

这里执行结果正确。

2)在 LD_LIBRARY_PATH 环境变量中加上库所在路径

$ export LD_LIBRARY_PATH=pwd:$LD_LIBRARY_PATH

我们可以看到:libtest.so 的路径已经存在

$ ldd test

在这里插入图片描述

我们可以看一下结果:

$ ./test

在这里插入图片描述

也能得到正确结果。

3)添加/etc/ld.so.conf.d/*.conf文件。把库所在的路径加到文件末尾,并执行ldconfig刷新。

$ cd /etc/ld.so.conf.d/
$ ls

在这里插入图片描述

$ sudo vi my.conf
$ cat my.conf

/home/bruceou/demo/libtest.so

在/etc/ld.so.conf.d/下建立my.conf 里面只有一句/home/bruceou/demo/libtest.so即libtest.so的路径,然后执行ldconfig刷新即可。


3.3动态库总结

1.编译动态库
方法一:
命令:gcc -fPIC -Wall -c < filename>.c
命令:gcc -shared -o lib< name>.so < filename>.o

方法二:
命令:gcc < file1>.c < file2>.c < filen>.c -fPIC -shared -o lib< name>.so

2.安装路径
命令:cp lib< name>.so /usr/lib/lib< name>.so//管理员身份

3.动态库的链接
命令:gcc -o < preject_name> < tag_name>.c -L. -l< name>
或者:命令:gcc < tag_name>.c -L. -l< name> -o < preject_name>

4.运行可执行程序




欢迎访问我的网站

BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书


欢迎订阅我的微信公众号

在这里插入图片描述

这篇关于《C语言杂记》静态库和动态库(Linux版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120828

相关文章

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

Linux Mint Xia 22.1重磅发布: 重要更新一览

《LinuxMintXia22.1重磅发布:重要更新一览》Beta版LinuxMint“Xia”22.1发布,新版本基于Ubuntu24.04,内核版本为Linux6.8,这... linux Mint 22.1「Xia」正式发布啦!这次更新带来了诸多优化和改进,进一步巩固了 Mint 在 Linux 桌面

LinuxMint怎么安装? Linux Mint22下载安装图文教程

《LinuxMint怎么安装?LinuxMint22下载安装图文教程》LinuxMint22发布以后,有很多新功能,很多朋友想要下载并安装,该怎么操作呢?下面我们就来看看详细安装指南... linux Mint 是一款基于 Ubuntu 的流行发行版,凭借其现代、精致、易于使用的特性,深受小伙伴们所喜爱。对