- UID
- 1029342
- 性别
- 男
|
blob.png一个运行时进程的典型内存分布最简单来说分为两大部分:指令+数据。再细分一点,五部分:代码(指令),初始化数据区,未初始化数据区,堆,栈。 代码(指令,text)就不用说了,最静态的,就是只读的东西; 初始化数据,简单理解就是有初始值的变量、常量; 未初始化数据,只声明未给值的变量,运行前统统为0,之所以单独分出来,估计是性能考虑,因为这些东西都是0,没必要放在程序包里,也不用copy; 栈,程序运行记录,每个线程,也就是每个执行序列各有一个(看crash log最容易理解),都是编译的时候能确定好的,还有一个特点就是这里面的数据可以不用指针,也不会丢; 堆,最灵活的内存区,用途多多,动态分配和释放,编译时不能提前确定,我们的Objective-C对象都是这么来的,都存在这里,通常堆中的对象都是以指针来访问的,指针从线程栈中来,但不独属于某个线程,堆也是对复杂的运行时处理的基础支持,还有就是ARC还是MRR、“谁分配谁释放”说的都是堆上对象的管理;其实,这个内存中的布局方式大部分操作系统中的大部分进程都是类似的。Objective-C的程序包对运行时有着复杂的支持和内容划分,但也都是在这个大的框架下进行的。2. iOS的内存管理其实,iOS的内存管理和其它操作系统大同小异。这里按照苹果文档所述,重点对堆内存分配整理下。首先,iOS和其它系统一样,内存分页,每页4K。多个页构成一个region统一管理,负责管理的对象是VM object,其中包含了pager、size、resident pages等诸多属性。不管是Objective-C的[NSObject alloc],还是C代码的对内存分配,最终重任都会落到malloc库上,释放也是如此,最终都将使用malloc库中的free()。malloc库中有很多malloc的同族函数可以动态分配内存,会结合参数在free pages中进行最适分配。如果分配的内存比较大,可以直接使用vm_allocate,得到一个VM对象(与Linux类似),这个在实际使用前不分配物理内存。malloc的内部实现都是开源的,感兴趣的可以去了解去看。此外,对于malloc,还有一个Zone的概念(貌似与Linux的概念不完全相同),可以简单理解为一组free page单元,可以统一管理操作。默认情况,在第一次调用malloc时,系统会生成一个default zone,后续的默认分配在此进行。比如,malloc_zone_xxx()函数都是对特定的zone进行分配操作,执行zone->xxx()。最后强调一下iOS特别需要注意的点:当前的主流iPhone实际物理内存都不超过1G,可以说不算大。不过和Android机比起来,我不得不为苹果的设计称赞,1G空间利用得如此高效,性能不差,也控制了发热。那么在这仅有的1G内存中,iOS的操作系统更是抛弃了不必要的复杂——系统层面不支持App内存页换出。当内存吃紧时,对于可以重新载入的只读数据来说,直接清理掉,而对于可写的数据,只能通过App自己去管理维护。内存紧张时,iOS会向App发起memory warning,不配合释放足够内存者,杀!blob.pngApp调试时的物理内存情况上图是使用Activity Monitor调试时的一个截图,可以看到在尽量不释放自身内存的情况下(为了bug调试特意这么做的),支付宝钱包的内存可以做到502M物理内存占用。再稍微高一点点,系统就会连前台运行的App一起Kill掉。留下一个Unknown的log。 |
|