这是我以前去链家网面试的一个题目,当时回答不够全面,现在看了2016 WWDC以及Sunnyxx iDev大会的分享之后,感觉对这个问题有了一些简单的认识,就来总结下。如果大家有补充,麻烦评论下哦!

简单来说,点击 Run 之后 App 进行编译、汇编、链接、代码签名以及启动执行等操作

编译

编译主要依靠编译器来完成一系列的操作,主要的操作有预处理、词法分析、语法分析、语义分析、生成中间代码、生成目标代码以及目标代码优化

OS X 现在使用的编译器是 LLVM (Low Level Virtual Machine),在最初使用的是 GCC作为官方的编译器,但是由于下面的众多限制,apple 使用了自己的一套编译器

  • GCC 原名为GNU C语言编译器,它原本只能处理 C语言,后来扩展了Objective-CJava等语言,但是对于Objective-C的处理还是存在众多不便
  • GCC 效率低下、性能不强
  • 苹果开发自己的编译器,有利于开展自己的工具链,比如后期做 Swiftlldb 等

借用 sunnyxx的图片 来展现下 llvm 的基本架构

编译器分别编译器前端(clang)和编译器后端,编译器前端负责产生机器无关的中间代码,编译器后端负责对中间代码进行优化并转化为目标机器代码,对于为什么需要 中间代码这个东西,看个图就一目了然啦(IR:intermediate representation中间表示)

预编译

预编译主要用来处理那些源文件中以 #开头的预编译命令,比如#include

词法分析

将输入分解为一个个独立的词法符号,也叫单词符号(token)

 
 
1
2
3
4
// find a zero
float  matchZero(char *s) {
 
}

上面的小程序,返回下列单词流

 
 
1
FLOAT、ID(MATCHZERO)、LPAREN、CHAR、ID(S) 、RPAREN   // 大概了解即可,觉得背这些词法符号定义对目前 iOS 开发用处不大

注释、宏、空格、换行等都不是单词

语法分析

将符号化的字符串,转化抽象为可以被计算机存储的树形结构,即抽象语法树(AST),并验证语法的正确性,例如:忘记带分号

语义分析

语法分析只能完成语法层面的分析,无法对整个语句的真正意义进行判别,比如,讲一个浮点数赋值指针类型的时候,语义分析器就会发现类型不匹配,编译器提出相应的错误警告。

语义分析主要做的事情就是类型检查、以及符号表管理

生成中间代码

编译器前端负责产生机器无关的中间代码,编译器后端负责对中间代码进行优化并转化为目标机器代码

目标代码的生成与优化

编译器后端主要包括代码生成器、代码优化器。代码生成器将中间代码转换为目标代码,代码优化器主要是进行一些优化,比如删除多余指令,选择合适寻址方式等

汇编

目标代码需要经过汇编器处理,才能变成机器上可以执行的指令。生成对应的.o文件

链接

链接器(这里指的是静态链接器)将多个目标文件合并为一个可执行文件,在 OS X 和 iOS中的可执行文件是 Mach-O,对于Mach-O的文件格式可以参考这里,刚才所描述的过程其实可以用 sunnyxx的一页 ppt来进行总结

链接呢,又分为静态链接和动态链接

静态链接

静态链接:在编译链接期间发挥作用,把目标文件和静态库一起链接形成可执行文件

动态链接

动态链接:链接过程推迟到运行时再进行。对于动态链接和静态链接,各有千秋

  • 如果多个程序都用到了一个库,那么每个程序都要将其链接到可执行文件中,非常冗余,动态链接的话,多个程序可以共享同一段代码,不需要在磁盘上存多份拷贝,但是动态链接发生在启动或运行时,增加了启动时间,造成一些性能的影响。
  • 静态库不方便升级,必须重新编译,动态库的升级更加方便

代码签名

我们每次build之后,都会发现工程目录下多了一个.app文件

在 .app目录中,有又一个叫_CodeSignature的子目录,这是一个 plist文件,里面包含了程序的代码签名,你的程序一旦签名,就没有办法更改其中的任何东西,包括资源文件,可执行文件等,iOS系统会检查这个签名。

签名过程本身是由命令行工具 codesign 来完成的。如果你在 Xcodebuild一个应用,这个应用构建完成之后会自动调用codesign 命令进行签名,这也是Link之后的一个关键步骤。

启动

在经过一系列处理后,终于形成一个可以在系统上跑起来的可执行程序,剩下的就是启动运行

其实在启动过程中,dyld(动态链接器) 起了很重要的作用,进行动态链接,进行符号和地址的一个绑定

dyld 主要在启动过程中主要做了以下事情:

  • 加载所依赖的dylibs
  • Fix-ups:Rebase修正地址偏移,因为 OS X和 iOS 搞了一个叫 ASLR的东西来做地址偏移(随机化)来避免收到攻击
  • Fix-ups:Binding确定 Non-Lazy Pointer地址,进行符号地址绑定。
  • ObjC runtime初始化:加载所有类
  • Initializers:www.90168.org执行load 方法和__attribute__((constructor))修饰的函数

对于如何减少启动时间,今年的 WWDC 也有详细的阐述,可以在参考链接中找到相关的资料。

总结

那么总体的过程可以概括为:编译 – 汇编 – 静态链接 – 签名 – 启动(动态链接等操作)- 跑起来了

继续借用 Sunnyxx 的 ppt

点击 Run 之后发生了什么?的更多相关文章

  1. TProcedure,TMethod,TNotifyEvent,TWndMethod的区别,并模拟点击按钮后发生的动作

    忽然发现TProcedure和TNotifEvent的区别还挺大的: procedure TForm1.Button2Click(Sender: TObject); begin ShowMessage ...

  2. Google Earth Engine 批量点击RUN任务,批量取消正在上传的任务

    本文内容参考自: https://blog.csdn.net/qq_21567935/article/details/89061114 https://blog.csdn.net/qq_2156793 ...

  3. Windows中点击“关闭”button发生了什么?

    对于Windows操作,当用户点击"关闭"button时,窗体函数就会收到一个WM_DESTROY消息. 窗体函数应该调用PostQuitMessage(0) 向消息队列插入一个W ...

  4. idea点击RUN启动报错: Broken configuration due to unavailable plugin or invalid configuration dat

    今天照常打开idea,突然发现之前的启动配置出问题了,随后报了一个这个错: Run Configuration Error: Broken configuration due to unavailab ...

  5. pyspider安装后,点击run,报pyhton has stop working或python已停止运行的错误

    问题解决虽然只有几句话,但是背后花了一天时间,各种FQ搜索. pyspider目测只支持32位的系统,所以你下载32位的python安装就行了,然后安装pyspider运行就没有问题了,坑爹啊---- ...

  6. 笔试常考--浏览器输入一个URL点击回车之后发生了什么

    解析URL:浏览器首先对拿到的URL进行识别,抽取出域名字段. DNS解析: 查询浏览器缓存(浏览器会缓存之前拿到的DNS 2-30分钟时间),如果没有找到, 检查系统缓存,检查hosts文件,这个文 ...

  7. 点击一次按钮,发生多次ajax请求

    项目中遇到了两种情况: 1.点击一次发生两次请求. 原因:submit类型的按钮,默认有提交行为,发生两次提交的原因是在执行完ajax请求后,并没有阻止submit的行为,所以解决方法有两种: a.不 ...

  8. 各位客官!鼠标点击一个Button之后究竟发生了什么?您知道么?(C#)

    在谈论主题之前,让我们先简单回顾下事件的基础知识吧! 我们知道事件有发出(raises)事件的源,即event sender,也有接收事件通知(notifications)的接收者,即event re ...

  9. AS 2.0新功能 Instant Run

    Instant Run上手 作为一个Android开发者,很多的时候我们需要花大量的时间在bulid,运行到真机(虚拟机)上,对于ios上的Playground羡慕不已,这种情况将在Android S ...

随机推荐

  1. java操作数据库出错

    "无效的列索引"其实是个低级的错误 出错原因:1.sql串的?号数目和提供的变量数目不一致:例如:jdbcTemplate.update(sql, new Object[] {ne ...

  2. php命令行运行出现错误Call to undefined function curl_init()

    在windows命令行窗口下运行php命令,需要将php.exe所在的路径添加到Path环境变量,例如C:\wamp\bin\php\php5.4.3 启动Apache服务 在命令行中输入php te ...

  3. September 21st 2016 Week 39th Wednesday

    Don't try so hard, the best things come when you least expect them. 不要着急,最好的总会在最不经意的时候出现. Always tur ...

  4. 解药还是毒药(codevs 2594)

    2594 解药还是毒药  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description Smart研制出对 ...

  5. CSS居中布局总结

    居中布局 <div class="parent"> <div class="child">demo</div> </d ...

  6. Codeforces Round #304 C(Div. 2)(模拟)

    题目链接: http://codeforces.com/problemset/problem/546/C 题意: 总共有n张牌,1手中有k1张分别为:x1, x2, x3, ..xk1,2手中有k2张 ...

  7. Notice: Only variable references should be returned by reference(PHP版本兼容性问题)

    摘自:http://sushener.spaces.live.com/blog/cns!BB54050A5CFAFCDD!435.entry PHP5一个很让人恼火的一点就是BC(向后兼容)不是很理想 ...

  8. poj 1006:Biorhythms(水题,经典题,中国剩余定理)

    Biorhythms Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 110991   Accepted: 34541 Des ...

  9. C#在后台运行操作:BackgroundWorker的用法

    在我们的程序中,经常会有一些耗时较长的运算,为了保证用户体验,不引起界面不响应,我们一般会采用多线程操作,让耗时操作在后台完成,完成后再进行处理或给出提示,在运行中,也会时时去刷新界面上的进度条等显示 ...

  10. php的时间输出格式

    php中时间一般分为两种格式,一种是标准时间格式timestamp,即Y-m-d G:i:s.另一种就是时间戳. 例如: 一.标准时间与时间戳转换: //获得服务端系统时间 date_default_ ...