当前位置 博文首页 > 我的博客:五万字长文:C/C++ 面试知识总结(下)

    我的博客:五万字长文:C/C++ 面试知识总结(下)

    作者:[db:作者] 时间:2021-06-08 11:25

    接中篇部分:

    网络层

    • IP(Internet Protocol,网际协议)是为计算机网络相互连接进行通信而设计的协议。

    • ARP(Address Resolution Protocol,地址解析协议)

    • ICMP(Internet Control Message Protocol,网际控制报文协议)

    • IGMP(Internet Group Management Protocol,网际组管理协议)

    IP 网际协议

    IP 地址分类:

    • IP 地址 ::= {<网络号>,<主机号>}
    IP 地址类别网络号网络范围主机号IP 地址范围
    A 类8bit,第一位固定为 00 —— 12724bit1.0.0.0 —— 127.255.255.255
    B 类16bit,前两位固定为 10128.0 —— 191.25516bit128.0.0.0 —— 191.255.255.255
    C 类24bit,前三位固定为 110192.0.0 —— 223.255.2558bit192.0.0.0 —— 223.255.255.255
    D 类前四位固定为 1110,后面为多播地址
    E 类前五位固定为 11110,后面保留为今后所用

    应用:

    • PING(Packet InterNet Groper,分组网间探测)测试两个主机之间的连通性

    TTL(Time To Live,生存时间)该字段指定 IP 包被路由器丢弃之前允许通过的最大网段数量

    内部网关协议

    • RIP(Routing Information Protocol,路由信息协议)

    • OSPF(Open Sortest Path First,开放最短路径优先)

    外部网关协议

    • BGP(Border Gateway Protocol,边界网关协议)

    IP多播

    • IGMP(Internet Group Management Protocol,网际组管理协议)

    • 多播路由选择协议

    VPN 和 NAT

    • VPN(Virtual Private Network,虚拟专用网)

    • NAT(Network Address Translation,网络地址转换)

    路由表包含什么?

    1. 网络 ID(Network ID, Network number):就是目标地址的网络 ID。

    2. 子网掩码(subnet mask):用来判断 IP 所属网络

    3. 下一跳地址/接口(Next hop / interface):就是数据在发送到目标地址的旅途中下一站的地址。其中 interface 指向 next hop(即为下一个 route)。一个自治系统(AS, Autonomous system)中的 route 应该包含区域内所有的子网络,而默认网关(Network id:?0.0.0.0, Netmask:?0.0.0.0)指向自治系统的出口。

    根据应用和执行的不同,路由表可能含有如下附加信息:

    1. 花费(Cost):就是数据发送过程中通过路径所需要的花费。

    2. 路由的服务质量

    3. 路由中需要过滤的出/入连接列表

    运输层

    协议:

    • TCP(Transmission Control Protocol,传输控制协议)

    • UDP(User Datagram Protocol,用户数据报协议)

    端口:

    应用程序FTPTELNETSMTPDNSTFTPHTTPHTTPSSNMP
    端口号212325536980443161

    受限于公众号文章字数限制,后续部分请看【今天的第二篇推文】,

    TCP

    • TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,其传输的单位是报文段。

    特征:

    • 面向连接

    • 只能点对点(一对一)通信

    • 可靠交互

    • 全双工通信

    • 面向字节流

    TCP 如何保证可靠传输:

    • 确认和超时重传

    • 数据合理分片和排序

    • 流量控制

    • 拥塞控制

    • 数据校验

    TCP 首部

    TCP:状态控制码(Code,Control Flag),占 6 比特,含义如下:

    • URG:紧急比特(urgent),当?URG=1?时,表明紧急指针字段有效,代表该封包为紧急封包。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据), 且上图中的 Urgent Pointer 字段也会被启用。

    • ACK:确认比特(Acknowledge)。只有当?ACK=1?时确认号字段才有效,代表这个封包为确认封包。当?ACK=0?时,确认号无效。

    • PSH:(Push function)若为 1 时,代表要求对方立即传送缓冲区内的其他对应封包,而无需等缓冲满了才送。

    • RST:复位比特(Reset),当?RST=1?时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。

    • SYN:同步比特(Synchronous),SYN 置为 1,就表示这是一个连接请求或连接接受报文,通常带有 SYN 标志的封包表示『主动』要连接到对方的意思。

    • FIN:终止比特(Final),用来释放一个连接。当?FIN=1?时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。

    UDP

    • UDP(User Datagram Protocol,用户数据报协议)是 OSI(Open System Interconnection 开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,其传输的单位是用户数据报。

    特征:

    • 无连接

    • 尽最大努力交付

    • 面向报文

    • 没有拥塞控制

    • 支持一对一、一对多、多对一、多对多的交互通信

    • 首部开销小

    TCP 与 UDP 的区别

    1. TCP 面向连接,UDP 是无连接的;

    2. TCP 提供可靠的服务,也就是说,通过 TCP 连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付

    3. TCP 的逻辑通信信道是全双工的可靠信道;UDP 则是不可靠信道

    4. 每一条 TCP 连接只能是点到点的;UDP 支持一对一,一对多,多对一和多对多的交互通信

    5. TCP 面向字节流(可能出现黏包问题),实际上是 TCP 把数据看成一连串无结构的字节流;UDP 是面向报文的(不会出现黏包问题)

    6. UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如 IP 电话,实时视频会议等)

    7. TCP 首部开销20字节;UDP 的首部开销小,只有 8 个字节

    TCP 黏包问题

    原因

    TCP 是一个基于字节流的传输服务(UDP 基于报文的),“流” 意味着 TCP 所传输的数据是没有边界的。所以可能会出现两个数据包黏在一起的情况。

    解决
    • 发送定长包。如果每个消息的大小都是一样的,那么在接收对等方只要累计接收数据,直到数据等于一个定长的数值就将它作为一个消息。

    • 包头加上包体长度。包头是定长的 4 个字节,说明了包体的长度。接收对等方先接收包头长度,依据包头长度来接收包体。

    • 在数据包之间设置边界,如添加特殊符号?\r\n?标记。FTP 协议正是这么做的。但问题在于如果数据正文中也含有?\r\n,则会误判为消息的边界。

    • 使用更加复杂的应用层协议。

    TCP 流量控制

    概念

    流量控制(flow control)就是让发送方的发送速率不要太快,要让接收方来得及接收。

    方法

    利用可变窗口进行流量控制

    TCP 拥塞控制

    概念

    拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。

    方法
    • 慢开始( slow-start )

    • 拥塞避免( congestion avoidance )

    • 快重传( fast retransmit )

    • 快恢复( fast recovery

    TCP 传输连接管理

    因为 TCP 三次握手建立连接、四次挥手释放连接很重要,所以附上《计算机网络(第 7 版)-谢希仁》书中对此章的详细描述:https://github.com/huihut/interview/blob/master/images/TCP-transport-connection-management.png

    TCP 三次握手建立连接

    【TCP 建立连接全过程解释】

    1. 客户端发送 SYN 给服务器,说明客户端请求建立连接;

    2. 服务端收到客户端发的 SYN,并回复 SYN+ACK 给客户端(同意建立连接);

    3. 客户端收到服务端的 SYN+ACK 后,回复 ACK 给服务端(表示客户端收到了服务端发的同意报文);

    4. 服务端收到客户端的 ACK,连接已建立,可以数据传输。

    TCP 为什么要进行三次握手?

    【答案一】因为信道不可靠,而 TCP 想在不可靠信道上建立可靠地传输,那么三次通信是理论上的最小值。(而 UDP 则不需建立可靠传输,因此 UDP 不需要三次握手。)

    Google Groups . TCP 建立连接为什么是三次握手?{技术}{网络通信}

    【答案二】因为双方都需要确认对方收到了自己发送的序列号,确认过程最少要进行三次通信。

    知乎 . TCP 为什么是三次握手,而不是两次或四次?

    【答案三】为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

    《计算机网络(第 7 版)-谢希仁》

    【TCP 释放连接全过程解释】

    1. 客户端发送 FIN 给服务器,说明客户端不必发送数据给服务器了(请求释放从客户端到服务器的连接);

    2. 服务器接收到客户端发的 FIN,并回复 ACK 给客户端(同意释放从客户端到服务器的连接);

    3. 客户端收到服务端回复的 ACK,此时从客户端到服务器的连接已释放(但服务端到客户端的连接还未释放,并且客户端还可以接收数据);

    4. 服务端继续发送之前没发完的数据给客户端;

    5. 服务端发送 FIN+ACK 给客户端,说明服务端发送完了数据(请求释放从服务端到客户端的连接,就算没收到客户端的回复,过段时间也会自动释放);

    6. 客户端收到服务端的 FIN+ACK,并回复 ACK 给客户端(同意释放从服务端到客户端的连接);

    7. 服务端收到客户端的 ACK 后,释放从服务端到客户端的连接。

    TCP 为什么要进行四次挥手?

    【问题一】TCP 为什么要进行四次挥手? / 为什么 TCP 建立连接需要三次,而释放连接则需要四次?

    【答案一】因为 TCP 是全双工模式,客户端请求关闭连接后,客户端向服务端的连接关闭(一二次挥手),服务端继续传输之前没传完的数据给客户端(数据传输),服务端向客户端的连接关闭(三四次挥手)。所以 TCP 释放连接时服务器的 ACK 和 FIN 是分开发送的(中间隔着数据传输),而 TCP 建立连接时服务器的 ACK 和 SYN 是一起发送的(第二次握手),所以 TCP 建立连接需要三次,而释放连接则需要四次。

    【问题二】为什么 TCP 连接时可以 ACK 和 SYN 一起发送,而释放时则 ACK 和 FIN 分开发送呢?(ACK 和 FIN 分开是指第二次和第三次挥手)

    【答案二】因为客户端请求释放时,服务器可能还有数据需要传输给客户端,因此服务端要先响应客户端 FIN 请求(服务端发送 ACK),然后数据传输,传输完成后,服务端再提出 FIN 请求(服务端发送 FIN);而连接时则没有中间的数据传输,因此连接时可以 ACK 和 SYN 一起发送。

    【问题三】为什么客户端释放最后需要 TIME-WAIT 等待 2MSL 呢?

    【答案三】

    1. 为了保证客户端发送的最后一个 ACK 报文能够到达服务端。若未成功到达,则服务端超时重传 FIN+ACK 报文段,客户端再重传 ACK,并重新计时。

    2. 防止已失效的连接请求报文段出现在本连接中。TIME-WAIT 持续 2MSL 可使本连接持续的时间内所产生的所有报文段都从网络中消失,这样可使下次连接中不会出现旧的连接报文段。

    应用层

    DNS

    • DNS(Domain Name System,域名系统)是互联网的一项服务。它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS 使用 TCP 和 UDP 端口 53。当前,对于每一级域名长度的限制是 63 个字符,域名总长度则不能超过 253 个字符。

    域名:

    • 域名 ::= {<三级域名>.<二级域名>.<顶级域名>},如:blog.huihut.com

    FTP

    • FTP(File Transfer Protocol,文件传输协议)是用于在网络上进行文件传输的一套标准协议,使用客户/服务器模式,使用 TCP 数据报,提供交互式访问,双向传输。

    • TFTP(Trivial File Transfer Protocol,简单文件传输协议)一个小且易实现的文件传输协议,也使用客户-服务器方式,使用UDP数据报,只支持文件传输而不支持交互,没有列目录,不能对用户进行身份鉴定

    TELNET

    • TELNET 协议是 TCP/IP 协议族中的一员,是 Internet 远程登陆服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。

    • HTTP(HyperText Transfer Protocol,超文本传输协议)是用于从 WWW(World Wide Web,万维网)服务器传输超文本到本地浏览器的传送协议。

    • SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    • Socket 建立网络通信连接至少要一对端口号(Socket)。Socket 本质是编程接口(API),对 TCP/IP 的封装,TCP/IP 也要提供可供程序员做网络开发所用的接口,这就是 Socket 编程接口。

    WWW

    • WWW(World Wide Web,环球信息网,万维网)是一个由许多互相链接的超文本组成的系统,通过互联网访问
    URL
    • URL(Uniform Resource Locator,统一资源定位符)是因特网上标准的资源的地址(Address)

    标准格式:

    • 协议类型:[//服务器地址[:端口号]][/资源层级UNIX文件路径]文件名[?查询][#片段ID]

    完整格式:

    • 协议类型:[//[访问资源需要的凭证信息@]服务器地址[:端口号]][/资源层级UNIX文件路径]文件名[?查询][#片段ID]

    其中【访问凭证信息@;:端口号;?查询;#片段ID】都属于选填项 ?
    如:https://github.com/huihut/interview#cc

    HTTP

    HTTP(HyperText Transfer Protocol,超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 是万维网的数据通信的基础。

    请求方法

    方法意义
    OPTIONS请求一些选项信息,允许客户端查看服务器的性能
    GET请求指定的页面信息,并返回实体主体
    HEAD类似于 get 请求,只不过返回的响应中没有具体的内容,用于获取报头
    POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改
    PUT从客户端向服务器传送的数据取代指定的文档的内容
    DELETE请求服务器删除指定的页面
    TRACE回显服务器收到的请求,主要用于测试或诊断

    状态码(Status-Code)

    • 1xx:表示通知信息,如请求收到了或正在进行处理

    • 100 Continue:继续,客户端应继续其请求

    • 101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到 HTTP 的新版本协议

    • 2xx:表示成功,如接收或知道了

    • 200 OK: 请求成功

    • 3xx:表示重定向,如要完成请求还必须采取进一步的行动

    • 301 Moved Permanently: 永久移动。请求的资源已被永久的移动到新 URL,返回信息会包括新的 URL,浏览器会自动定向到新 URL。今后任何新的请求都应使用新的 URL 代替

    • 4xx:表示客户的差错,如请求中有错误的语法或不能完成

    • 400 Bad Request: 客户端请求的语法错误,服务器无法理解

    • 401 Unauthorized: 请求要求用户的身份认证

    • 403 Forbidden: 服务器理解请求客户端的请求,但是拒绝执行此请求(权限不够)

    • 404 Not Found: 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置 “您所请求的资源无法找到” 的个性页面

    • 408 Request Timeout: 服务器等待客户端发送的请求时间过长,超时

    • 5xx:表示服务器的差错,如服务器失效无法完成请求

    • 500 Internal Server Error: 服务器内部错误,无法完成请求

    • 503 Service Unavailable: 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的 Retry-After 头信息中

    • 504 Gateway Timeout: 充当网关或代理的服务器,未及时从远端服务器获取请求

    更多状态码:菜鸟教程 . HTTP状态码

    其他协议
    • SMTP(Simple Main Transfer Protocol,简单邮件传输协议)是在 Internet 传输 Email 的标准,是一个相对简单的基于文本的协议。在其之上指定了一条消息的一个或多个接收者(在大多数情况下被确认是存在的),然后消息文本会被传输。可以很简单地通过 Telnet 程序来测试一个 SMTP 服务器。SMTP 使用 TCP 端口 25。

    • DHCP(Dynamic Host Configuration Protocol,动态主机设置协议)是一个局域网的网络协议,使用 UDP 协议工作,主要有两个用途:

    • 用于内部网络或网络服务供应商自动分配 IP 地址给用户

    • 用于内部网络管理员作为对所有电脑作中央管理的手段

    • SNMP(Simple Network Management Protocol,简单网络管理协议)构成了互联网工程工作小组(IETF,Internet Engineering Task Force)定义的 Internet 协议族的一部分。该协议能够支持网络管理系统,用以监测连接到网络上的设备是否有任何引起管理上关注的情况。

    网络编程

    Socket

    Socket 中的 read()、write() 函数

    ssize_t read(int fd, void *buf, size_t count);
    ssize_t write(int fd, const void *buf, size_t count);
    
    read()
    • read 函数是负责从 fd 中读取内容。

    • 当读成功时,read 返回实际所读的字节数。

    • 如果返回的值是 0 表示已经读到文件的结束了,小于 0 表示出现了错误。

    • 如果错误为 EINTR 说明读是由中断引起的;如果是 ECONNREST 表示网络连接出了问题。

    write()
    • write 函数将 buf 中的 nbytes 字节内容写入文件描述符 fd。

    • 成功时返回写的字节数。失败时返回 -1,并设置 errno 变量。

    • 在网络程序中,当我们向套接字文件描述符写时有俩种可能。

    • (1)write 的返回值大于 0,表示写了部分或者是全部的数据。

    • (2)返回的值小于 0,此时出现了错误。

    • 如果错误为 EINTR 表示在写的时候出现了中断错误;如果为 EPIPE 表示网络连接出现了问题(对方已经关闭了连接)。

    Socket 中 TCP 的三次握手建立连接

    我们知道 TCP 建立连接要进行 “三次握手”,即交换三个分组。大致流程如下:

    1. 客户端向服务器发送一个 SYN J

    2. 服务器向客户端响应一个 SYN K,并对 SYN J 进行确认 ACK J+1

    3. 客户端再想服务器发一个确认 ACK K+1

    只有就完了三次握手,但是这个三次握手发生在 Socket 的那几个函数中呢?请看下图:

    从图中可以看出:

    1. 当客户端调用 connect 时,触发了连接请求,向服务器发送了 SYN J 包,这时 connect 进入阻塞状态;

    2. 服务器监听到连接请求,即收到 SYN J 包,调用 accept 函数接收请求向客户端发送 SYN K ,ACK J+1,这时 accept 进入阻塞状态;

    3. 客户端收到服务器的 SYN K ,ACK J+1 之后,这时 connect 返回,并对 SYN K 进行确认;

    4. 服务器收到 ACK K+1 时,accept 返回,至此三次握手完毕,连接建立。

    Socket 中 TCP 的四次握手释放连接

    上面介绍了 socket 中 TCP 的三次握手建立过程,及其涉及的 socket 函数。现在我们介绍 socket 中的四次握手释放连接的过程,请看下图:

    图示过程如下:

    1. 某个应用进程首先调用 close 主动关闭连接,这时 TCP 发送一个 FIN M;

    2. 另一端接收到 FIN M 之后,执行被动关闭,对这个 FIN 进行确认。它的接收也作为文件结束符传递给应用进程,因为 FIN 的接收意味着应用进程在相应的连接上再也接收不到额外数据;

    3. 一段时间之后,接收到文件结束符的应用进程调用 close 关闭它的 socket。这导致它的 TCP 也发送一个 FIN N;

    4. 接收到这个 FIN 的源发送端 TCP 对它进行确认。

    这样每个方向上都有一个 FIN 和 ACK。

    数据库

    • 数据库事务四大特性:原子性、一致性、分离性、持久性

    • 数据库索引:顺序索引、B+ 树索引、hash 索引
      MySQL 索引背后的数据结构及算法原理

    • SQL 约束 (Constraints)

    范式

    • 第一范式(1NF):属性(字段)是最小单位不可再分

    • 第二范式(2NF):满足 1NF,每个非主属性完全依赖于主键(消除 1NF 非主属性对码的部分函数依赖)

    • 第三范式(3NF):满足 2NF,任何非主属性不依赖于其他非主属性(消除 2NF 主属性对码的传递函数依赖)

    • 鲍依斯-科得范式(BCNF):满足 3NF,任何非主属性不能对主键子集依赖(消除 3NF 主属性对码的部分和传递函数依赖)

    • 第四范式(4NF):满足 3NF,属性之间不能有非平凡且非函数依赖的多值依赖(消除 3NF 非平凡且非函数依赖的多值依赖)

    设计模式

    各大设计模式例子参考:CSDN专栏 . C++ 设计模式 系列博文

    设计模式工程目录

    单例模式

    单例模式例子

    抽象工厂模式

    抽象工厂模式例子

    适配器模式

    适配器模式例子

    桥接模式

    桥接模式例子

    观察者模式

    观察者模式例子

    设计模式的六大原则

    • 单一职责原则(SRP,Single Responsibility Principle)

    • 里氏替换原则(LSP,Liskov Substitution Principle)

    • 依赖倒置原则(DIP,Dependence Inversion Principle)

    • 接口隔离原则(ISP,Interface Segregation Principle)

    • 迪米特法则(LoD,Law of Demeter)

    • 开放封闭原则(OCP,Open Close Principle)

    链接装载库

    内存、栈、堆

    一般应用程序内存空间有如下区域:

    • 栈:由操作系统自动分配释放,存放函数的参数值、局部变量等的值,用于维护函数调用的上下文

    • 堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统回收,用来容纳应用程序动态分配的内存区域

    • 可执行文件映像:存储着可执行文件在内存中的映像,由装载器装载是将可执行文件的内存读取或映射到这里

    • 保留区:保留区并不是一个单一的内存区域,而是对内存中受到保护而禁止访问的内存区域的总称,如通常 C 语言讲无效指针赋值为 0(NULL),因此 0 地址正常情况下不可能有效的访问数据

    栈保存了一个函数调用所需要的维护信息,常被称为堆栈帧(Stack Frame)或活动记录(Activate Record),一般包含以下几方面:

    • 函数的返回地址和参数

    • 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量

    • 保存上下文:包括函数调用前后需要保持不变的寄存器

    堆分配算法:

    • 空闲链表(Free List)

    • 位图(Bitmap)

    • 对象池

    “段错误(segment fault)” 或 “非法操作,该内存地址不能 read/write”

    典型的非法指针解引用造成的错误。当指针指向一个不允许读写的内存地址,而程序却试图利用指针来读或写该地址时,会出现这个错误。

    普遍原因:

    • 将指针初始化为 NULL,之后没有给它一个合理的值就开始使用指针

    • 没用初始化栈中的指针,指针的值一般会是随机数,之后就直接开始使用指针

    编译链接

    各平台文件格式

    平台可执行文件目标文件动态库/共享对象静态库
    Windowsexeobjdlllib
    Unix/LinuxELF、outosoa
    MacMach-Oodylib、tbd、frameworka、framework

    编译链接过程

    1. 预编译(预编译器处理如?#include#define?等预编译指令,生成?.i?或?.ii?文件)

    2. 编译(编译器进行词法分析、语法分析、语义分析、中间代码生成、目标代码生成、优化,生成?.s?文件)

    3. 汇编(汇编器把汇编码翻译成机器码,生成?.o?文件)

    4. 链接(连接器进行地址和空间分配、符号决议、重定位,生成?.out?文件)

    现在版本 GCC 把预编译和编译合成一步,预编译编译程序 cc1、汇编器 as、连接器 ld

    MSVC 编译环境,编译器 cl、连接器 link、可执行文件查看器 dumpbin

    目标文件

    编译器编译源代码后生成的文件叫做目标文件。目标文件从结构上讲,它是已经编译后的可执行文件格式,只是还没有经过链接的过程,其中可能有些符号或有些地址还没有被调整。

    可执行文件(Windows 的?.exe?和 Linux 的?ELF)、动态链接库(Windows 的?.dll?和 Linux 的?.so)、静态链接库(Windows 的?.lib?和 Linux 的?.a)都是按照可执行文件格式存储(Windows 按照 PE-COFF,Linux 按照 ELF)

    目标文件格式
    • Windows 的 PE(Portable Executable),或称为 PE-COFF,.obj?格式

    • Linux 的 ELF(Executable Linkable Format),.o?格式

    • Intel/Microsoft 的 OMF(Object Module Format)

    • Unix 的?a.out?格式

    • MS-DOS 的?.COM?格式

    PE 和 ELF 都是 COFF(Common File Format)的变种

    目标文件存储结构
    功能
    File Header文件头,描述整个文件的文件属性(包括文件是否可执行、是静态链接或动态连接及入口地址、目标硬件、目标操作系统等)
    .text section代码段,执行语句编译成的机器代码
    .data section数据段,已初始化的全局变量和局部静态变量
    .bss sectionBSS 段(Block Started by Symbol),未初始化的全局变量和局部静态变量(因为默认值为 0,所以只是在此预留位置,不占空间)
    .rodata section只读数据段,存放只读数据,一般是程序里面的只读变量(如 const 修饰的变量)和字符串常量
    .comment section注释信息段,存放编译器版本信息
    .note.GNU-stack section堆栈提示段

    其他段略

    链接的接口————符号

    在链接中,目标文件之间相互拼合实际上是目标文件之间对地址的引用,即对函数和变量的地址的引用。我们将函数和变量统称为符号(Symbol),函数名或变量名就是符号名(Symbol Name)。

    如下符号表(Symbol Table):

    Symbol(符号名)Symbol Value (地址)
    main0x100
    Add0x123

    Linux 的共享库(Shared Library)

    Linux 下的共享库就是普通的 ELF 共享对象。

    共享库版本更新应该保证二进制接口 ABI(Application Binary Interface)的兼容

    命名

    libname.so.x.y.z

    • x:主版本号,不同主版本号的库之间不兼容,需要重新编译

    • y:次版本号,高版本号向后兼容低版本号

    • z:发布版本号,不对接口进行更改,完全兼容

    路径

    大部分包括 Linux 在内的开源系统遵循 FHS(File Hierarchy Standard)的标准,这标准规定了系统文件如何存放,包括各个目录结构、组织和作用。

    • /lib:存放系统最关键和最基础的共享库,如动态链接器、C 语言运行库、数学库等

    • /usr/lib:存放非系统运行时所需要的关键性的库,主要是开发库

    • /usr/local/lib:存放跟操作系统本身并不十分相关的库,主要是一些第三方应用程序的库

    动态链接器会在?/lib/usr/lib?和由?/etc/ld.so.conf?配置文件指定的,目录中查找共享库

    环境变量

    • LD_LIBRARY_PATH:临时改变某个应用程序的共享库查找路径,而不会影响其他应用程序

    • LD_PRELOAD:指定预先装载的一些共享库甚至是目标文件