【iOS】——编译链接和动态链接器

前言

计算机语言分为机器语言:汇编语言,高级语言。
可以将高级语言分为两种:1,编译语言和解释型语言(直译式语言)。

img

编译型语言(一次性翻译)

编译型语言的程序只要经过编译器编译之后,每次运行程序都可以直接运行如oc,swift等

解释型语言(逐步进行解释执行)

解释语言编写的程序在每次运行时都需要通过解释器对程序进行动态解释和执行,如php,javascript等

编译链接过程:

1,预处理:macro 宏, import 头文件替换及处理其他的预编译指令,产生.i文件。(都是以#号开头)

2,编译:把预处理完的一系列文件进行一系列词法、语法、静态分析,并且优化后生成相应的汇编代码,产生.s文件;

3,汇编:汇编器将汇编代码生成机器指令,输出目标文件,产生.o文件(根据汇编指令和机器指令的对照表一一翻译就可以了);

4,链接:在一个文件中可能会到其他文件,因此,还需要将编译生成的目标文件和系统提供的文件组合到一起,这个过程就是链接。经过链接,最后生成可执行文件。

img

预处理(预编译)-> 产生.i文件

使用终端到main.m所在文件夹,使用命令:

clang -E main.m -o main.i

处理源代码文件中的以"#"开头的预编译指令:

  • "#define"删除并展开对应宏定义。

  • 处理所有的条件预编译指令。如#if/#ifdef/#else/#endif。

  • "#include/#import"包含的文件递归插入到此处。

  • 删除所有的注释"//或/**/"。

  • 添加行号和文件名标识。如“# 1 “main.m””,编译调试会用到。

编译 -> 产生.s文件

编译器:用来把源文件转换为更低级的语言,xcode使用的clang前端编译器的作用就是把源代码转化为更为低级的LLVM IR,这个LLVM IR是操作系统无关的,然后后端编译器LLVM通过这个中间语言来进行下一步二进制文件的产出。这要得益于LLVM的三层架构,假如你需要增加一种语言,只需要增加一种前端,如过你需要增加一种处理器架构,也只需要增加一种后端。

img

编译器前端:Clang编译器前端的任务是进行:语法分析,语义分析,生成中间代码(intermediate representation )。在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行。Clang 是一个C、C++、Objective-C和Objective-C++编程语言的编译器前端。

公用优化器:将生成的中间文件进行优化,去除冗余代码,进行结构优化。将优化后的中间代码再次转换,变成汇编语言,并再次进行优化,最后将各个文件代码转换为机器代码并链接。

编译器后端:

clang -S main.i -o main.s

编译过程也分为 词法分析 -> 语法分析 -> 静态分析 最后优化生成相应的汇编代码,得到.s文件

词法分析:源代码的字符序列分割成一个个token(关键字、标识符、字面量、特殊符号),比如把标识符放到符号表(静态链接那篇,重点讲符号表)。

语法分析:把词法分析生成的token生成抽象语法树 AST,此时运算符号的优先级确定了;有些符号具有多重含义也确定了,比如“*”是乘号还是对指针取内容;表达式不合法、括号不匹配等,都会报错。

静态分析:分析类型声明和匹配问题。比如整型和字符串相加,肯定会报错。

一般会把类型分为两类:动态的和静态的。动态的在运行时做检查,静态的在编译时做检查。以往,编写代码时可以向任意对象发送任何消息,在运行时,才会检查对象是否能够响应这些消息。由于只是在运行时做此类检查,所以叫做动态类型。

静态类型,是在编译时做检查。当在代码中使用 ARC 时,编译器在编译期间,会做许多的类型检查:因为编译器需要知道哪个对象该如何使用。

中间语言生成和优化:CodeGen根据AST自顶向下遍历逐步翻译成 LLVM IR,并且在编译期就可以确定的表达式进行优化,比如代码里t1=2+6,可以优化t1=8。(假如开启了bitcode,)

目标代码生成与优化:根据中间语言生成依赖具体机器的汇编语言。并优化汇编语言。这个过程中,假如有变量且定义在同一个编译单元里,那给这个变量分配空间,确定变量的地址。假如变量或者函数不定义在这个编译单元,得链接时候,才能确定地址。

汇编 -> 产生.o文件

clang -c main.s -o main.o

汇编器将上一步生成的可读的汇编代码转化为机器代码。最终产物就是 以 .o 结尾的目标文件。

链接

clang main.o -o main

这一阶段是将上个阶段生成的目标文件和引用的静态库链接起来,最终生成可执行文件(Mach-O),链接器解决了目标文件和库之间的链接。

动态库和静态库

动态库

动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行时才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新

  • 动态库把对一些库函数的链接载入推迟到程序运行的时期。
  • 可以实现进程之间的资源共享。(因此动态库也称为共享库)将一些程序升级变得简单。
  • 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。

静态库

在程序编译期的链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。

  • 程序在运行时独立运行,不需要依赖外部库。

  • 静态库的调用通常比动态库的调用更快,因为不需要动态链接

  • 生成的可执行程序较大。如果多个使用静态链接生成的程序同时运行会占用大量的内存空间静态库一旦被编译链接到可执行文件中,想要更新或替换静态库的代码需要重新编译整个程序。

动态库和静态库的区别

静态库

  • 在编译时加载

  • 优点:代码装载和执行速度比动态库快。

  • 缺点:浪费内存和磁盘空间,模块更新困难。

    动态库

  • 在运行时加载

  • 优点:体积比静态库小很多,更加节省内存。

  • 缺点:代码装载和执行速度比静态库慢。

动态链接器

动态链接器的定义

动态链接器通常指的是dylddyld是它负责处理程序和动态库(dylib,动态链接库)之间的链接操作。dyld的主要任务是在程序启动时解析和加载所需的动态库,并解决这些库中的符号引用。

  1. 加载动态库dyld在程序启动时会加载指定的动态库。这包括系统库和应用程序可能依赖的任何第三方库。dyld能够延迟加载某些库,直到它们被实际使用,这有助于提高启动速度和内存效率。
  2. 解析符号: 当程序引用了一个动态库中的函数或变量时,dyld会查找并绑定这些符号到正确的地址。这个过程称为符号解析,它确保了程序能正确地访问库中的功能。
  3. 重定位dyld还负责重定位,这意味着它会调整库中的地址,以确保它们在进程的虚拟地址空间中正确放置。这通常涉及修改库内部的指针,使它们指向正确的内存位置。
  4. 缓存dyld使用缓存机制来存储已加载的库和已解析的符号,这样在后续的程序执行中就不需要重复加载或解析相同的内容,从而加快了程序的运行速度。
  5. 懒惰链接(Lazy Binding): 为了进一步提高性能,dyld可以采用懒惰链接策略,只在程序真正尝试访问一个库中的符号时才解析该符号。这避免了在程序启动时不必要的工作。
  6. 可执行文件和动态库的集成: 在iOS中,dyld不仅处理动态库,还负责加载和执行可执行文件本身。可执行文件中包含了dyld的启动信息,告诉它需要加载哪些库和如何初始化程序。
  7. 安全特性dyld还实现了一些安全特性,如ASLR(地址空间布局随机化),通过随机化库的加载地址来增加攻击者预测内存布局的难度,从而提高系统的安全性。

dyld2和dyld3的区别

dyld2dyld3dyld的不同版本,它们在功能和性能上有一些关键区别

下图为dyld2执行流程:

img

下图为dyld3执行流程:

img

相比于dyld 3,dyld 2的加载过程没有那么优化。它没有将工作分成两个阶段,而是直接在进程中完成所有任务,包括解析、查找依赖、映射文件、查找符号以及绑定和重定位等。这意味着这些操作可能会阻塞主线程,导致应用程序启动速度变慢。此外,由于没有生成和使用闭包,dyld 2也没有提供额外的安全性保障来防止恶意软件尝试修改或注入代码到正在运行的应用程序中。

dyld 3 包含这三个部分:

  • 进程外 Mach-O 分析器和编译器 (out-of-process mach-o parser
    由于 dyld 2 存在的问题,dyld 3 中将采用提前写入把结果数据缓存成文件的方式构成一个 lauch closure(可以理解为缓存文件)
  • 进程内引擎 执行 launch closure 处理 (in-process engine)
    验证”lauch closures“是否正确,映射dylib,执行main函数。此时,它不再需要分析mach-o header和执行符号查找,节省了不少时间。
  • launch closure 缓存服务 (launch closure cache )
    系统程序的 lauch closure 直接内置在 shared cache 中,而对于第三方APP,将在APP安装或更新时生成,这样就能保证 launch closure 总是在 APP 打开之前准备好。

dyld 3的符号缺失问题

dyld 2 默认采取的是 lazy symbol 的符号加载方式,但在 dyld 3中,在 App 启动之前,符号解析的结果已经在 lauch closure 内了,所以 lazy symbol 就不再需要。这时,如果有符号缺失的情况,APP 的行为会有不同:在 dyld 2 中,首次调用缺失符号时 APP 会 crash;而 dyld 3 中,缺失符号会导致 APP 一启动就会 crash。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3249733.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Spring如何管理Mapper

目录 一、背景二、猜测三、源码查看步骤1、创建MapperScannerConfigurer.java2、MapperScan注解3、MapperScannerRegistrar执行registerBeanDefinitions方法4、MapperScannerConfigurer执行postProcessBeanDefinitionRegistry方法5、执行doscan6、设置beanClass7、使用jdk生成代…

sql常见50道查询练习题

sql常见50道查询练习题 1. 表创建1.1 表创建1.2 数据插入 2. 简单查询例题(3题)2.1 查询"李"姓老师的数量2.2 查询男生、女生人数2.3 查询名字中含有"风"字的学生信息 3. 日期相关例题(6题)3.1 查询各学生的年龄3.2 查询本周过生日的…

解决:Linux上SVN 1.12版本以上无法直接存储明文密码

问题:今天在Linux机器上安装了SVN,作为客户端使用,首次执行SVN相关操作,输入账号密码信息后,后面再执行SVN相关操作(比如"svn update")还是每次都需要输入密码。 回想以前在首次输入…

Typora 1.5.8 版本安装下载教程 (轻量级 Markdown 编辑器),图文步骤详解,免费领取

文章目录 软件介绍软件下载安装步骤激活步骤 软件介绍 Typora是一款基于Markdown语法的轻量级文本编辑器,它的主要目标是为用户提供一个简洁、高效的写作环境。以下是Typora的一些主要特点和功能: 实时预览:Typora支持实时预览功能&#xff0…

云监控(华为) | 实训学习day3(10)

实现数据的增删改查 SpringBoot框架模式 向送外卖一样理解 写程序 1、准备食材(java bean) 2、菜谱(pojo接口->预制->sql 语句) 3、service处理 4、controller 派送 5、用户请求->页面 一、Spring Boot实现增加 第一步:食材(表),用户增加,这里还是用户…

使用Python和Pandas进行数据分析:入门与实践

目录 引言 准备工作 安装Python与Pandas 导入Pandas库 Pandas基础 数据结构 创建Series和DataFrame 读取数据 数据探索 查看数据 数据清洗 数据可视化 实战案例:分析销售数据 引言 在当今数据驱动的时代,数据分析已成为各行各业不可或缺的…

如何高效定制视频扩散模型?卡内基梅隆提出VADER:通过奖励梯度进行视频扩散对齐

论文链接:https://arxiv.org/pdf/2407.08737 git链接:https://vader-vid.github.io/ 亮点直击: 引入奖励模型梯度对齐方法:VADER通过利用奖励模型的梯度,对多种视频扩散模型进行调整和对齐,包括文本到视频和…

机器学习的持续交付-CD4ML 端到端自动化构建部署机器学习应用

机器学习的持续交付-CD4ML 端到端自动化构建部署机器学习应用 原文:Continuous Delivery for Machine Learning - CD4ML 关键字:持续部署、持续交付、机器学习、CD4ML 作者:Danilo Sato, Arif Wider, Christoph Windheuser 译者:周…

synergy配置

今天介绍一个电脑同步软件synergy。 我们开发时一般会用两套设备,如果使用两套键盘操作起来会很麻烦,这个软件就是解决这个问题,可以使用一套键盘同时操作两台电脑,另一台作为客户端被控制。 安装 在两台电脑上各自下载安装syne…

55 TCP协议

目录 协议段格式确认应答(ACK)机制序号标志位超时重传连接管理机制延迟应答捎带应答流量控制滑动窗口拥塞控制面向字节流粘包问题异常情况小结文件和socket的关系基于tcp应用层协议udp和tcp对比udp实现可靠传输 全称为“传输控制协议(Transm…

【BUG】已解决:note: This is an issue with the package mentioned above,not pip.

已解决:note: This is an issue with the package mentioned above,not pip. 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博主英杰,211科班出身,就职于医疗科技公司,热衷…

ELK 8.14版本搭建

1.架构图 2.基础环境准备: 2.1 关闭防火墙和selinux [rootlocalhost ~]# setenforce 0 [rootlocalhost ~]# sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config [rootlocalhost ~]# cat /etc/selinux/config # This file controls the state of SEL…

手机恢复回收站清空的照片,3个方法与注意事项【小米/华为/vivo】

你们是否曾遭遇过这样的困境:清空回收站后,突然发现其中有几张非常重要的照片?那种懊悔与焦虑,简直可以写成一部“手机用户的心酸史”。这篇文章来拯救你啦!恢复回收站清空的照片的方法可不少,究竟是哪3个方…

uni-app开发日志:unicloud使用时遇到的问题解决汇总(不断补充)

插件安装后提示与原数据库表冲突(2024.7.18) 安装uni-admin后再安装uni-cms,在uni-admin中添加好菜单,结果提示该错误 回到hbuilder中uniCloud/database中找到冲突的部分 比较一下,选中老的删除 opendb-news-articl…

【转盘案例-弹框-修改Bug-完成 Objective-C语言】

一、我们来看示例程序啊 1.旋转完了以后,它会弹一个框,这个框,是啥, Alert 啊,AlertView 也行, AlertView,跟大家说过,是吧,演示过的啊,然后,我们就用iOS9来做了啊,完成了以后,我们要去弹一个框, // 弹框 UIAlertController *alertController = [UIAlertContr…

maven项目打成可运行的jar及pom中的依赖一同打包

maven项目打jar及pom中的依赖一同打包 最近开发中有个需求,不部署新的服务,只jar包执行 那maven项目中,代码如何以jar的方式运行、如何把代码打成jar、pom中的依赖如何与代码一同打到jar包中? 1、代码如何以jar的方式运行&…

222.买卖股票的最佳时机(力扣)

代码解决 class Solution { public:int maxProfit(vector<int>& prices) {// 初始化最小买入价为第一个价格int min1 prices[0];// 初始化最大利润为0int max1 0;// 从第二天开始遍历价格数组for (int i 1; i < prices.size(); i) {// 计算当前价卖出的利润&a…

FastAPI 学习之路(五十九)封装统一的json返回处理工具

在本篇文章之前的接口&#xff0c;我们每个接口异常返回的数据格式都不一样&#xff0c;处理起来也没有那么方便&#xff0c;因此我们可以封装一个统一的json。 from fastapi import status from fastapi.responses import JSONResponse, Response from typing import Unionde…

SSM 整合(Spring + MyBatis;Spring + Spring MVC)

1. SSM 整合(Spring MyBatis&#xff1b;Spring Spring MVC) 文章目录 1. SSM 整合(Spring MyBatis&#xff1b;Spring Spring MVC)2. 引入相关依赖3. SSM 整合3.1 创建包结构 4. Spring 整合 MyBatis4.1 编写 jdbc.properties4.2 编写 DataSourceConfig 数据源配置4.3 编…

【LLM】基于ColossalAI-0.3.6对llama2-7B-Chat做全参数微调

文章目录 环境准备工作下载llama2-7B下载ColossalAI数据集准备准备原始数据集数据集处理开始训练准备训练脚本运行脚本推理验证加载模型推理环境 操作系统: ubuntu22.04机器规格: CPU:96c;内存:736 GiB;GPU:8 * NVIDIA V100 (32GB)软件信息: Python 3.11.5;ColossalA…