二进制文件和库之间有什么区别?

2023-05-16

问题

我正在尝试了解文件系统层次结构标准。我已经查找了二进制文件和库,并且据我目前的理解:

二进制文件是二进制格式的计算机可读代码文件,它们直接用位控制CPU和处理器。

为了方便起见,是可由各种程序使用的函数-例如,当您需要PHP Javascript中的模块时。

这种理解正确吗?如果是这样,为什么我们仍将库和二进制文件分开?有些库二进制文件,对不对?还有一些二进制文件(cat,less,date,rm,cp等)被使用和重用,就好像它们是库一样。有人可以帮助解释它们的区别,并帮助我为这两个单词找到更好的定义吗?谢谢。

回答

您的理解大体上是正确的,但还需要考虑一些其他事项:

  1. “二进制”是指人类无法理解的东西。这通常是指机器代码,但是从这个意义上讲,许多其他文件也是二进制文件,其中大多数多媒体格式就是一个很好的例子。但是,FHS对于该术语有更具体的用法。
  2. 库可以是二进制代码。实际上,其中的大部分内容/lib都将是编译成机器代码的库。
  3. 尽管诸如此类cat的东西在外壳脚本中使用,例如对库中的代码的调用,但它们并不是FHS的库,因为它们可以自己运行。

由于上述几点,在不编写标准文档的人们中,更常见的术语是:

  • 目标文件:这些是本机编译的机器代码,但是甚至无法运行或不可调用。它们通常具有.o扩展名,除非它们属于其他类别之一,并且除构建软件外,在大多数系统上几乎从未见过。我在这里列出了它们,因为它们对于理解以下几条内容很重要。
  • 可执行文件:这些文件主要由可直接运行的自包含代码组成。它们可以是可以由内核直接加载的特殊格式的目标文件(诸如catbashpython,都是这种类型的可执行文件),也可以由本身是可执行文件的某些中间程序来解释(Minecraft pydoc,和cowsay都是示例)这类可执行文件)。第一种可执行文件在UNIX系统上几乎没有文件扩展名,而第二种可执行文件则可能有也可能没有。这就是FHS所谓的“二进制文件”。他们可以从其他可执行文件运行,但需要调用特殊功能调用它们(fork()以及exec()在C和C ++,东西出来的subprocess Python等模块),并作为单独的进程运行。
  • 库:这些文件包含可重用的代码,这些代码可被另一个库或可执行文件调用。一旦加载了库(在谈论已编译的代码时称为“链接”),库中的代码就会(通常)被其他代码直接调用,并在与调用它的代码相同的过程中运行。共有三种类型的库:
    1. 静态库:这些是原始库。它们由一个归档文件(通常为AR格式)组成,内部有大量目标文件,每个目标函数对应一个。目标文件被链接到使用它们的可执行文件中,因此仅使用静态库的可执行文件本质上100%独立于任何其他代码。在UNIX系统上,它们通常具有.a扩展名。静态库的概念在编译的编程语言之外并不存在。
    2. 动态库:这些是当今最常用的库类型。动态库是一个特殊的对象文件,通常.so在UNIX 上具有扩展名(.dllWindows 上是标准扩展名),该文件在运行时由使用它的可执行文件加载。/lib在生产系统上可以找到的大多数是动态库。
    3. 模块:这相当于解释语言的动态库。处理与编译语言略有不同,并且与编译语言不同,文件可能既是模块又是可执行文件(http.server有关示例,请参见Python标准库)。

另外附上一篇比较完整的讲解各种文件区别的文章。

头文件和库文件区别,动态库和静态库的区别,动静态库的生成

  • 一、什么是头文件?什么是库文件?有什么区别?
    • 先说总结
    • 目标文件
  • 二、什么是静态库?什么是动态库?有什么区别?
  • 三、为什么只用在程序头部写上包含的头文件,头文件中并没有实现内容就可以使用声明的函数呢?
    • 动静态库区别
        • 1.可执行文件大小不一样
        • 2.占用磁盘大小不一样
        • 3.拓展性与兼容性不一样
        • 4.依赖不一样
        • 5.复杂性不一样
        • 6.加载速度不一样
  • 四、如何生成动静态库文件
      • 静态库的生成
      • 库文件的搜索路径
      • 动态库的生成
        • 总结
  • 参考

一、什么是头文件?什么是库文件?有什么区别?

先说总结

头文件是包含函数声明,宏定义,类的声明的文件。

在linux中一般头文件会在/usr/include中,如果没有可以使用 locate命令查找文件所在位置。

库文件是一种目标文件,静态库是可重定位目标文件,动态库是共享目标文件。(后面有解释)

一般在/usr/lib、/usr/lib64、/lib、/lib64都包含库文件

头文件是在预处理时使用;库文件是链接时使用。

头文件内容还是高级语言内容;库文件是二进制文件。

目标文件

在解释静态库和动态库之前,需要简单了解一下什么是目标文件。目标文件常常按照特定格式来组织,在linux下,它是ELF格式(Executable Linkable Format,可执行可链接格式),而在windows下是PE(Portable Executable,可移植可执行)。

而通常目标文件有三种形式:

  • 可执行目标文件。即我们通常所认识的,可直接运行的二进制文件。

  • 可重定位目标文件。包含了二进制的代码和数据,可以与其他可重定位目标文件合并,并创建一个可执行目标文件。

  • 共享目标文件。它是一种在加载或者运行时进行链接的特殊可重定位目标文件。

    使用readelf -a filename 可以查看目标文件的ELF格式

二、什么是静态库?什么是动态库?有什么区别?

静态库在linux中是以.a(archive)为后缀,作用是在进行链接生成可执行文件时,从静态库文件中拷贝需要的内容到最终的可执行文件中。

//在使用gcc编译时采用 -static选项来进行静态文件的链接:

gcc -c main.c

gcc -static -o main main.o

动态库在linux中是以.so(shared object)为后缀,它并不在链接时将需要的二进制代码都拷贝到可执行文件中,而是拷贝一些重定位和符号表信息,当程序运行时需要的时候再通过符号表从动态库中获取。

//使用gcc编译默认采用动态链接

gcc -o main main.c

三、为什么只用在程序头部写上包含的头文件,头文件中并没有实现内容就可以使用声明的函数呢?

首先要熟悉程序编译过程

预处理->编译->汇编->链接

  • 预处理(preprocessing)的时候把头文件内容包含进来。

gcc -E -o main.i main.c

  • 编译,但不包括汇编(compilation, do not assemble)将预处理后的文件转换成汇编代码。

gcc -S -o main.S main.i

  • 汇编将编译后的程序转换为二进制文件,也就是可重定向目标文件。

gcc -c -o main.o main.S

  • 链接将具体的动态库或者静态库中的代码(也就是包的头文件中的代码实现部分)拷贝代码或拷贝符号表的方式,生成可执行目标文件。

gcc -o main main.o

动静态库区别

1.可执行文件大小不一样

静态链接的可执行文件要比动态链接的可执行文件大得多,因为它将需要用到的代码从二进制文件中拷贝了一份,而动态链接仅仅是复制了一些重定位和符号表信息。

2.占用磁盘大小不一样

如果有多个可执行文件,那么静态库中的同一个函数的代码就会被复制多次,而动态库只有一份,因此使用静态库占用的磁盘空间相对比动态库要大。

3.拓展性与兼容性不一样

如果静态库中某个函数的实现变了,那么可执行文件必须重新编译,而对于动态链接生成的可执行文件,只需要更新动态库本身即可,不需要重新编译可执行文件。正因如此,使用动态库的程序方便升级和部署。

4.依赖不一样

静态连接的可执行文件不需要依赖其他的内容即可运行,而动态链接的可执行文件必须依赖动态库的存在。所以如果你在安装一些软件的时候,提示某个动态库不存在的时候也就不奇怪了。

即便如此,系统中一般存在一些大量公用的库,所以使用动态库并不会有什么问题。

5.复杂性不一样

相对来说,动态库的处理要比静态库要复杂,例如如何在运行时确认地址?多个进程如何共享一个动态库?当然,作为调用者我们不需要关注,另外动态库版本的管理也是一项技术活。这也不在本文的讨论范围。

6.加载速度不一样

由于静态库在链接时就和可执行文件在一块了,而动态库在加载或者运行时才链接,因此,对于同样的程序,静态链接的要比动态链接加载更快。所以选择静态库还是动态库是空间和时间的考量。但是通常来说,牺牲这点性能来换取程序在空间上的节省和部署的灵活性是值得的。再加上局部性原理,牺牲的性能并不多。(局部性原理是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储单元都趋于聚集在一个较小的连续区域中。)

四、如何生成动静态库文件

静态库的生成

//1.先写出相应的.h文件和对应的.c文件

//2.编译.c文件

//3.使用ar工具将.o文件归档生成.a静态库文件

[root@localhost linux]# ls
add.c add.h main.c sub.c sub.h
[root@localhost linux]# gcc -c add.c -o add.o
[root@localhost linux]# gcc -c sub.c -o sub.o
生成静态库
[root@localhost linux]# ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create)
查看静态库中的目录列表
[root@localhost linux]# ar -tv libmymath.a
rw-r–r-- 0/0 1240 Sep 15 16:53 2017 add.o
rw-r–r-- 0/0 1240 Sep 15 16:53 2017 sub.o
t:列出静态库中的文件
v:verbose 详细信息
[root@localhost linux]# gcc main.c -L. -lmymath
-L 指定库路径
-l 指定库名
测试目标文件生成后,静态库删掉,程序照样可以运行。

注意:静态库文件和动态库文件的命名规则是libxxxx.so/libxxxx.a,在进行 链接时只用lxxxx即可

库文件的搜索路径

  • 从左往右搜索-L指定的目录
  • 有环境变量指定的目录(LIBRAY_PATH)
  • 由系统指定的目录
    • /usr/lib
    • /usr/local/lib

动态库的生成

  • shared:表示生成共享库格式
  • fPIC:产生位置无关码(position independent code)

示例:

[root@localhost linux]# gcc -fPIC -c sub.c add.c

[root@localhost linux]# gcc -shared -o libmymath.so *.o

[root@localhost linux]# ls

add.c add.h add.o libmymath.so main.c sub.c sub.h sub.o

总结

静态库和动态库的具体链接方式并没在本文讨论,本文仅仅介绍动静态库的区别和是什么和怎么生成,对于我来说已经足够。更多内容需要读者自行阅读相关书籍。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二进制文件和库之间有什么区别? 的相关文章

  • 串口通信库总结

    C 43 43 开源库 Windows和linux下好用的串口通讯API库 serial 在 C 43 43 xff0c 跨平台 xff0c 串口库编写 https github com wjwwood serial boost网络串口通信
  • 【C语言开源库】lw_oopc:轻量级的C语言面向对象编程框架

    文章目录 轻量级的面向对象C语言编程框架LW OOPC介绍摘要s为什么要用面向对象 为什么不直接使用C 43 43 LW OOPC是什么 LW OOPC宏介绍问题描述解决方案方案的可扩展性如何 LW OOPC最佳实践LW OOPC的优点LW
  • Go语言基础语法入门

    一 下载及安装 被河蟹了 xff01 xff01 xff01 二 入门教程 Go 语言结构 在我们开始学习 Go 编程语言的基础构建模块前 xff0c 让我们先来了解 Go 语言最简单程序的结构 Go Hello World 实例 Go 语
  • docker环境安装tomcat

    一 安装tomcat 1 查找tomcat镜像 docker search tomcat 2 安装指定版本的tomcat镜像 docker pull tomcat 9 0 二 启动tomcat镜像 docker run d p 8080 8
  • Go语言并发详解

    文章目录 一 Go语言并发简述 xff08 并发的优势 xff09 进程 线程并发 并行协程 线程Goroutine 介绍channel 二 Go语言goroutine xff08 轻量级线程 xff09 使用普通函数创建 goroutin
  • C/C++ 服务器/后台开发学习路线总结及准备

    文章目录 一 前言二 总结网上的学习路线三 之前的一些相关博客整理 一 前言 最近要新开一个非常重要的系列 xff0c C C 43 43 服务器 后台开发 这个系列将会包括非常多的内容 xff0c 难度也会比之前的系列大很多 xff0c
  • 学了十几种编程语言后,我有哪些感受?

    转一下鱼皮大佬的文章 xff1a https mp weixin qq com s Eier53 flKEtxj yGIQs8A 大家好 xff0c 我是鱼皮 学编程 5 年多了 xff0c 我学过十几种编程语言 xff0c 比如 C C
  • 【C/C++服务器开发】什么是服务器?服务器分类及构建一个简单的服务器系统

    文章目录 一 服务器的定义二 服务器的分类1 外形2 CPU指令集3 用途1 web服务器WEB简介协议WWW简介发展和特点服务器特点工作原理 2 应用服务器定义分类静态动态 概括区别应用服务器和WEB服务器的区别Web型应用程序型 3 文
  • 函数式编程初探及Haskell简介

    诞生50多年之后 xff0c 函数式编程 xff08 functional programming xff09 开始获得越来越多的关注 不仅最古老的函数式语言Lisp重获青春 xff0c 而且新的函数式语言层出不穷 xff0c 比如Erla
  • 【C/C++服务器开发】同步与异步、阻塞与非阻塞、同步调用和异步调用的概念

    同步与异步 首先我们要明确的是 xff0c 同步和异步都是针对两个或者两个以上的事物来说的 比如当我们在网上购物看中一件物品 xff0c 然后去浏览该商品详情的时候 xff0c 首先页面会先发送一个请求 xff0c 后台服务器查询对应商品的
  • C语言注册机制原理及实现

    文章目录 一 前言二 注册机制1 问题描述2 如何解决这种问题定时器运用注册机制定时器的使用方法 一 前言 想要理解注册机制 xff0c 首先我们需要对函数指针 xff0c 回调函数有一定的了解 之前我的一篇博客已经详细的讲解了 xff1a
  • 【C/C++服务器开发】socket网络编程函数接口详解

    文章目录 一 前言TCP 网络编程结合三次握手连接的 TCP socket结合四次次挥手的 TCP socket 二 socket常用函数和数据结构1 socket 函数2 bind 函数sockaddr in 结构体in addr 结构体
  • 【C/C++服务器开发】socket网络编程函数接口的灵活运用

    文章目录 一 前言二 服务器代码实例1 V1 0 xff1a 一个最简单的服务器实例2 V1 1 xff1a 可以持续响应客户端请求的服务器 一 前言 往期博客回顾 xff1a C C 43 43 服务器 后台开发学习路线总结及准备 C C
  • 【LeetCode刷题日记】[104. 二叉树的最大深度]

    一 题目 二 解析 C 43 43 span class token keyword class span span class token class name Solution span span class token punctua
  • Failed to configure a DataSource: ‘url‘ attribute

    一 完整的错误信息 APPLICATION FAILED TO START Description Failed to configure a DataSource 39 url 39 attribute is not specified
  • 【C/C++服务器开发】具备丰富功能和可以同时响应多个客服端的服务器

    文章目录 一 前言二 功能更加丰富的服务器三 让服务器可以同时响应多个客户端请求1 单线程 进程2 多进程并发父进程 xff1a 子进程 xff1a 3 多线程并发主线程 xff1a 子线程 xff1a 四 技术准备 一 前言 往期博客回顾
  • 【LeetCode刷题日记】[859. 亲密字符串]

    C 43 43 span class token keyword class span span class token class name Solution span span class token punctuation span
  • C++中原生数组、STL的vector、STL的array的区别

    文章目录 一 数组一维数组一维数组初始化一维数组元素的引用 二 STL的arrayC 43 43 STL array随机访问迭代器 xff08 精讲版 xff09 begin end 和 cbegin cend rbegin rend 和
  • Docker 入门教程

    推荐两篇阮一峰老师的文章 xff0c 网上看了很多Docker教程 xff0c 发现还是这个让我理解了什么是Docker xff0c 怎么用Docker Docker 入门教程 Docker 微服务教程 再放一个比较全的Docker教程 x

随机推荐