iOS:App 编译和启动原理

编译原理:

将编译过程分为前端和后端两部分处理

Clang(编译器前端):GCC的替代品,Clang的编译速度比GCC快
1.Lexer:读入源文件,并将其转化成字符流。
2.Parser:将字符流转换成AST(抽象语法树)。
3.SemanticAnalysis:对输入的AST进行语法检查。
4. Code Generation:代码生成,将AST转换成低层次的IR指令。

LLVM(编译器后端):底层虚拟机(Low Level Virtual Machine)
1.Optimization:分析IR指令,将其中潜在会拖慢运行速度的指令干掉。
2. AsmPrinter:通过IR(中间码)生成特定CPU架构的汇编代码。
3.Assemble :将汇编代码转化成机器码。
4. Linker:将机器码链接成可执行程序或动态码。
在这里插入图片描述

BitCode

当我们提交程序到 App Store 上时,Xcode 会将程序编译为一个中间表现形式( bitcode )。然后 App store 会再将这个 bitcode 编译为可执行的 64 位或 32 位程序

BitCode是什么?

BitCode 类似于一个中间码,被上传到 AppStore 之后,苹果会根据下载应用的用户的手机指令集类型生成只有该指令集的二进制进行下发,从而达到精简安装包体积的目的。
在这里插入图片描述

指令集

iOS 模拟器没有 arm 指令集,编译运行的是 x86/i386 指令集

模拟器的指令集:

4S:-5i386
5S以上: X64_86

真机(iOS设备)的默认指令集:
armv6设备: iPhone,iPhone2,iPhone3G
armv7设备: iPhone3GS,iPhone4,iPhone4S
armv7s设备: iPhone5,iPhone5C
arm64设备: iPhone5S 以上

但是我们在编译的时候偶尔会报出 i386,x86_64 的错误?
在这里插入图片描述
解决办法:
查看静态库是否支持 i386/x86_64 的方法:

  1. 如果是 .a 文件:
    • 打开终端,使用 lipo -info 静态包地址 .a 查看
  2. 如果是 framework 文件:
    • cd 到 framework 内部,之后在使用 lipo -info xxxFramework 查看

启动原理

Apple 在 2016 年的 WWDC 大会上提到:
建议应用的启动时间控制在 400ms 之下。并且必须在 20s 以内完成启动,否则系统会 kill 掉应用程序。那么话说我们如何知道 app 的在启动到调用 main( ) 方法之前的时间呢?
应用的启动分为 Pre-main 和 mian 两部分:

Pre-main 时间:从在屏幕上点击 app icon 开始,到应用执行到 main() 方法都是属于 Pre-main 时间

以下就是 Pre-main 部分在这里插入图片描述

1. dylib loading time: 载入动态库,包括引用的第三方库和自定义的动态库,Apple官方建议尽量少使用自定义的动态库,或者考虑合并多个动态库。
2. rebase/binding time: 重构和绑定,rebase会修正调整处理图像的指针,并且会设置指向绑定(binding)外部的图像指针。(即Rebase修正内部的指针指向,Bind 修正外部指针指向)
3. ObjC setup time: 在Objective-C的运行时(runtime),需要对类(class),类别(category)进行注册以及选择器分配
4. Initializer time: 是执行+initialize方法的时间

查看 Pre-main 时间的方法:

在 iOS10 之前的系统中,我们无处得知其中的细节。而在 iOS10 系统中,可以通过简单在 Xcode 设置,在控制台就可以打印出 Pre-main 的具体信息细节,见以下两个截图:
在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验1 词法分析 一、 实验目的 调试并完成一个词法分析程序,加深对词法分析原理的理解。 二、 实验要求 1、 待分析的简单语言的词法 (1) 关键字: begin if then while do end 所有关键字都是小写。 (2) 运算符和界符: := + – * / < <= <> > >= = ; ( ) # (3) 其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义: ID=letter(letter| digit)* NUM=digit digit * (4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。 2、 各种单词符号对应的种别码 单词符号 种别码 单词符号 种别码 begin 1 : 17 if 2 := 18 then 3 > 20 while 4 <> 21 do 5 <= 22 end 6 < 23 letter(letter| digit)* 10 >= 24 digit digit * 11 = 25 * 13 ; 26 / 14 ( 27 + 15 ) 28 - 16 # 0 3、 词法分析程序的功能 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 三、结果验证 给定源程序 begin x:=9; if x>0 then x:=2*x+1/3; end# 输出结果。 四、源程序代码如下: #include<stdio.h> #include<string.h> #include<iostream.h> char prog[80],token[8]; char ch; int syn,p,m=0,n,sum=0; //p是缓冲区prog的指针,m是token的指针 char *rwtab[6]={"begin","if","then","while","do","end"}; void scaner() { for(n=0;n<8;n++) token[n]=NULL; ch=prog[p++]; while(ch=='_') 执行语句1; if((判断ch是字母字符的条件)) { m=0; while((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')||(ch>='0'&&ch<='9')) { token[m++]=ch; ch=prog[p++];} token[m++]='\0'; p--; syn=10; for(n=0;n<6;n++) if(加入判断条件) {syn=n+1; break; } } else if(判断ch是数字字符的条件)' { sum=0; while(ch>='0'&&ch<='9') { sum=sum*10+ch-'0'; ch=prog[p++]; } p--;执行语句2; } else ………完成剩余程序代码 }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值