这是我以前去链家网面试的一个题目,当时回答不够全面,现在看了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. .NET微信公众号开发-5.0微信支付

    一.前言 在开始做这个功能之前,我们要做的第一件事情就是思考,如何做这个微信支付,从哪里开始,从哪里入手,官方的sdk说明什么的,有没有什么官方的demo,还有就是老板给我的一些资料齐全不,那些要申请 ...

  2. sdut 2445 小学数学

    小学数学 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 题目链接:http://acm.sdut.edu.cn/sdutoj/p ...

  3. SQL高级查询技巧(两次JOIN同一个表,自包含JOIN,不等JOIN)

    掌握了这些,就比较高级啦 Using the Same Table Twice 如下面查询中的branch字段 SELECT a.account_id, e.emp_id, b_a.name open ...

  4. Flex导出excel报表

    sheetToExcel.java 1 package tree; 2 import java.io.BufferedInputStream; 3 import java.io.File; 4 imp ...

  5. SSIS Dataflow使用存储过程不能检索列名

    在项目中遇到一个问题,需要在Dataflow中调用一个存储过程,然后把结果生成一个csv文件. 然而在dataflow调用存储过程中遇到了问题,SP不能正确的返回列名. 在SSMT里面明明是可以查出数 ...

  6. 如何调试SSIS包之跟踪变量赋值

    在SSIS开发工具SQL Server Data Tools中提供了调试功能,可以让我们方便的跟踪参数赋值或者数据流条数.本文主要介绍了如何使用SSDT的调试功能. Part A: Script ta ...

  7. Windows下Apache服务器中自动配置二级子域名

    今天我们介绍的这个办法,只需要简单修改 httpd-vhosts.conf 文件,配合 .htaccess 文件即可实现自动配置二级域名. 我们这里以 wpchina.com 为例,以下代码中的 wp ...

  8. python生成RSS(PyRSS2Gen)

    既然能够用python解析rss,那么也顺带研究下生成rss. 其实很简单,只是生成一个比较特殊点的xml文档而已. 这里我使用了PyRss2Gen,用法很简单,看代码就知道了,如下: import ...

  9. NS2中trace文件分析

    ns中模拟出来的时间最终会以trace文件的形式告诉我们,虽然说一般都是用awk等工具分析trace文件,但是了解trace文件的格式也是必不可少的.下面就介绍一下无线网络模拟中trace文件的格式. ...

  10. hdu 4751 2013南京赛区网络赛 二分图判断 **

    和以前做过的一个二分图颇为相似,以前的是互相不认识的放在一组,这个是互相认识的,本质上是相同的 是 hdu 2444 #include<cstdio> #include<iostre ...