iOS基础概念6
CPU和GPU
CPU
在iOS程序中,负责对象的创建和销毁、对象属性的调整、布局的计算、文本的
计算和排版规格、图片的格式转码和解码、图像的绘制(Core Graphic)
GPU
图形处理器,负责纹理的渲染,计算等等
流程:
【代码创建】
对象的创建和销毁、对象属性的调整、布局的计算、文本的计算和排版规格、图
片的格式转码和解码、图像的绘制(Core Graphic)
【CPU 】:
执行,并计算相关数据
完成后交由GPU
【GPU执行】:
将CPU提交来的数据进行渲染计算,
然后生成可以在屏幕上显示的色值数据,
GPU:将数据提交给 帧缓存
【帧缓冲区】
iOS 双缓存: 前帧缓存,后帧缓存
交由 【视频控制器】 处理,去缓存读取帧
【屏幕成像:】
将帧显示到屏幕上,如果缓存没有就等下一帧
屏幕成像原理
垂直同步信号(VSync)
1. 屏幕每隔固定时间屏幕发出VSync。
2. 之后每次从帧缓存读取一帧完整数据显示
水平同步信号(HSync)
将一屏分成很多行,每次取一行的数据,
显示完一行发出 HSync 信号,再取一行直到
一屏显示完成
帧率
60FPS(Frame per Second 帧/秒)
一秒钟刷新60次
VSync 下 16.6毫秒发出一次
影响因素 CPU
CALayer 与 UIView : 无触摸事件时可考虑使用CALayer
布局: Frame 与 autolayout
UIImageView 显示size 大小不同被裁剪
线程的最大并发数
耗时操作放到子线程处理(比如文本的尺寸计算、绘制,图片的解码、绘制)
影响因素 GPU
短时间内大量的图片显示,可使用合成框架(涉及区域点击事件)
最大纹理尺寸是4096*4096,不要过大
减少视图的数量和层级,透明的视图
离屏渲染
光栅化操作 layer.shouldRasterize = YES
遮罩设置 layer.mask
圆角设置 layer.masksToBounds = YES&layer.cornerRadius>0
CoreGraphics
切图
阴影设置 layer.shadowXXX
设置layer.shadowPath
耗电
CPU处理 Processing
网络 Networking
定位 Location
图像 Graphics
耗电优化
降低CPU、GPU功耗
少用定时器
优化I/O操作
大量数据批量一次性写入
考虑用dispatch_io,它提供了基于GCD的异步操作文件I/O的API。使用它时,
系统会优化磁盘的访问
使用数据库
网络优化
减少、压缩网络数据
如果多次请求的结果是相同的,尽量使用缓存
使用断点续传,否则网络不稳定时可能会导致多次传输相同内容
网络不可用时,不要尝试执行网络请求
让用户取消长时间运行或者速度很慢的网络操作,设置合适的超时时间
批量传输,比如,下载视频流是,不要传输很小的数据包,直接下载整个文件或
者一大块一大块下载。如果下载广告,一次性多下载一些,然后慢慢的拿出来展
示。如果狭隘电子邮件,就一次下载多封,不要一封一封下载
定位优化
如果只是需要确定用户的位置,最好用CLLocationManager的requestLocation
方法。定位完成后,会自动让定位硬件断电。
如果不是导航引用,尽量不要实时更新位置,定位完毕就关闭掉定位服务
需要后台定位时,尽量设置pauseLocationUpdateAutomatically为YES,这
样,如果用户不太可能移动的时候,系统就会自动暂停位置更新。
尽量不要使用startMonitoringSignificantLocationChanges,优先考虑
startMonitoringForRegion:
硬件检测优化
用户移动、摇晃、倾斜设备时,会产生动作事件(motion),这些事件是由加速
度计、陀螺仪、磁力传感器等硬件检测的。在不需要检测的场合,应该及时关闭
这些硬件。
虚拟内存 & 物理内存
数据访问
不再直接通过物理地址访问
1 进程 --> 2 CPU 访问虚拟内存 ,虚拟内存偏移映射真实内存,--> 3 访问
真实内存地址
虚拟内存
虚拟内存 提高了【CPU的利用率】
本质就是: 一张虚拟地址和物理地址对应关系的映射表
每个进程都有一个独立的`虚拟内存`
大小是4G固定的
每个虚拟内存又会划分为一个一个的`页`(页的大小在`iOS中是16K,其他的是
4K`)
每次加载都是以页为单位加载的
进程间是无法互相访问的,
保证了进程间数据的安全性
缺页异常
如果在访问时,虚拟地址的内容未加载到物理内存,会发生`缺页异常
(pagefault)`,将当前进程阻塞掉,此时需要先将数据载入到物理内存,然后
再寻址,进行读取。这样就避免了内存浪费
ASLR技术
ASLR:地址空间配置随机加载
问题:
虚拟内存的起始地址 0 与大小 4G 都是固定的,非常容易被破解
利用随机方式配置数据地址空间,使某些敏感数据(例如APP登录注册、支付相
关代码)配置到一个恶意程序无法事先获知的地址,令攻击者难以进行攻击
寻址:
因物理地址是随机配置的,实际需要:
正确的内存地址 = ASLR地址 + 偏移值
通用二进制文件
不同CPU平台支持的指令不同,比如`arm64`和x86
`将多种架构的Mach-O文件打包在一起` 供系统自己选择
也被称为`胖二进制格式`
1》文件大小比较大:
比单一架构的二进制文件大很多,会占用大量的磁盘空间,
2》内存占用不影响:
但由于系统会自动选择最合适的,不相关的架构代码不会占用内存空间,且`执
行效率高`了
指令
查看
查看当前Mach-O的架构:
lipo -info MachO文件
合并
lipo -create MachO1 MachO2 -output 输出文件路径
拆分
lipo MachO文件 –thin 架构 –output 输出文件路径
Mach-O
可执行文件格式,苹果系统可识别 mach object
查看Mach-O
- 【方式一】otool终端命令:`otool -l Mach-O文件名`
-【方式二】 `MachOView`工具(推荐):将Mach-O可执行文件拖动到
`MachOView`工具打开
Mach-O 的
几种文件类型
- `Executable`:可执行文件
- `Dylib`:动态链接库
- `Bundle`:无法被链接的动态库,只能在运行时使用dlopen加载
- `Image`:指的是Executable、Dylib和Bundle的一种
- `Framework`:包含Dylib、资源文件和头文件的集合
Mach-O 包含三个模块:
1 : header
2 :Load Commands
3 :Data
结构
- `Header Mach-O头部`:主要是Mach-O的cpu架构,文件类型以及加载命令
等信息
- `Load Commands 加载命令`:描述了文件中数据的具体组织结构,不同的数
据类型使用不同的加载命令表示
- `Data 数据`:数据中的每个段(segment)的数据都保存在这里,段的概念
与ELF文件中段的概念类似。每个段都有一个或多个部分,它们放置了具体的数
据与代码,主要包含代码,数据,例如符号表,动态符号表等等
Header
包含了 整个Mach-O文件的【关键信息】
基础架构、系统类型、指令条数等
- magic:0xfeedface(32位) 0xfeedfacf(64位),系统内核用来判断是否是
mach-o格式
- cputype:CPU类型,比如ARM
- cpusubtype:CPU的具体类型,例如arm64、armv7
- filetype:由于可执行文件、目标文件、静态库和动态库等都是mach-o格
式,所以需要filetype来说明mach-o文件是属于哪种文件
- ncmds:sizeofcmds:LoadCommands加载命令的条数(加载命令紧跟
header之后)
- sizeofcmds:LoadCommands加载命令的大小
- flags:标志位标识二进制文件支持的功能,主要是和系统加载、链接有关
- reserved:保留字段
文件类型
#define MH_OBJECT 0x1 /* 目标文件*/
#define MH_EXECUTE 0x2 /* 可执行文件*/
#define MH_DYLIB 0x6 /* 动态库*/
#define MH_DYLINKER 0x7 /* 动态链接器*/
#define MH_DSYM 0xa /* 存储二进制文件符号信息,用于debug分析*/
Load Commands
【作用】:
Mach-O文件中 Load Commands :
主要是用于【加载指令】
【记录信息】:
动态链接器的位置、
程序的入口、
依赖库的信息、
代码的位置、
符号表的位置
mach-o 唯一标识
函数起始地址
代码签名信息
等等
【segment_command 段加载命令】:
- cmd:表示加载命令类型,
- cmdsize:表示加载命令大小(还包括了紧跟其后的nsects个section的大
小)
- segname:16个字节的段名字
- vmaddr:段的虚拟内存起始地址
- vmsize:段的虚拟内存大小
- fileoff:段在文件中的偏移量
- filesize:段在文件中的大小
- maxprot:段页面所需要的最高内存保护(4 = r,2 = w,1 = x)
- initprot:段页面初始的内存保护
- nsects:段中section数量
- flags:其他杂项标志位
- 从fileoff(偏移)处,取filesize字节的二进制数据,放到内存的vmaddr处的
vmsize字节。(fileoff处到filesize字节的二进制数据,就是“段”)
- 每一个段的权限相同(或者说,编译时候,编译器把相同权限的数据放在一
起,成为段),其权限根据initprot初始化。initprot指定了如何通过读/写/执行
位初始化页面的保护级别
- 段的保护设置可以动态改变,但是不能超过maxprot中指定的值(在iOS中,
+x和+w是互斥的)
Data
Data区域`存储了具体的 【只读、可读写代码】
例如方法、符号表、字符表、代码数据、连接器所需的数据(重定向、符号绑定
等)。主要是存储具体的数据
三大区:
__TEXT 代码段:只读,包括函数,和只读的字符串
__DATA 数据段:读写,包括可读写的全局变量等
__LINKEDIT`: __LINKEDIT包含了方法和变量的元数据(位置,偏移量),以
及代码签名等信息
在`Data`区中,`Section`占了很大的比例。
主要集中体现在`TEXT`和`DATA`两段里
Section
section - __TEXT
__TEXT.__text
__TEXT.__cstring
_TEXT.__const
标签 2
_TEXT.__stubs
标签 3
_TEXT.__stubs_helper
标签 4
_TEXT.__objc_methname
标签 5
_TEXT.__objc_methtype
标签 6
_TEXT.__objc_classname
标签 7
主程序代码
C语言字符串
const 关键字修饰的常量
标签 2
用于 Stub 的占位代码,
很多地方称之为桩代码
标签 3
当 Stub 无法找到真正的符
号地址后的最终指向
标签 4
Objective-C 方法名称
标签 5
Objective-C 方法类型
标签 6
Objective-C 类名称
标签 7
section - __DATA
__DATA.__data
初始化过的可变数据
解释
_DATA.__la_symbol_ptr
lazy binding 的指针表,表中的
指针一开始都指向 __stub_helper
解释
_DATA.nl_symbol_ptr
非 lazy binding 的指针表,每个表项中的指针都指向一个在装载过程中,被动
态链机器搜索完成的符号
解释
_DATA.__const
没有初始化过的常量
解释
_DATA.__cfstring
程序中使用的 Core Foundation 字符串(CFStringRefs)
解释
_DATA.__bss
BSS,存放为初始化的全局变量,即常说的静态内存分配
解释
_DATA.__common
没有初始化过的符号声明
解释
_DATA.__objc_classlist
Objective-C 类列表
解释
_DATA.__objc_protolist
Objective-C 原型
解释
_DATA.__objc_imginfo
Objective-C 镜像信息
解释
__DATA.__objc_selfrefs
Objective-C self 引用
解释
__DATA.__objc_protorefs
Objective-C 原型引用
解释
_DATA.__objc_superrefs
Objective-C 超类引用
解释