iOS开发 技术集锦MacOS开发 技术集锦系统层知识

深入解析Mac OS X & iOS 操作系统 学习笔记

2016-11-02  本文已影响431人  CoderKo1o

可执行文件

在UNIX中,任何文件都可以通过简单的 chmod +x 命令标记为可执行文件。但是不能保证文件可执行,这个标记只是告诉操作系统内核将这个文件读入内存,然后寻找一个头签名,又称为“魔数(magic)”,据此可以确定精确的可执行格式。

OS X支持的可执行格式:

胖二进制文件头格式.png Mach-O文件头.png

动态库

Mach-O镜像中有很多对外部的库和符号的引用。由动态链接器来绑定,动态链接器是内核执行LC_DYLINKER 加载命令时启动的,通常使用的是/usr/lib/dyld 作为动态链接器,链接器接管刚创建的进程的控制权,因为内核将进程的入口点设置为链接器的入口点

共享库缓存

共享库缓存(shard library cache)是dyld 支持的另外一个机制。共享库缓存指的是一些库经过预先链接,然后保存在磁盘上的一个文件中。共享缓存在iOS 中尤为重要,在iOS 中大部分常用库都被缓存了

库的运行时加载

OS X 中提供的运行时动态库加载API类似于POSIX提供的API,但是OS X 的实现完全不同:

Cocoa 和 Carbon 为dl* 系列函数提供了高级包装,以及CFBundle/NSBundle 对象,用于加载Mach-O bundle文件

dyld 的特性

进程

和其他任何抢占式的多任务操作系统一样,进程作为一个正在执行的程序的是实例是UNIX的一个基本概念。这个实例可以通过Progress ID(进程ID,即PID)来唯一辨识。进程还会将其和父进程的亲属关系保存在父进程ID(Parent Progress ID, PPID)中。父进程可以通过fork(或通过posix_spawn)创建子进程,并且预期子进程会消亡。UNIX进程的生母意义就是运行,然后在运行结束之后返回一个整数。子进程返回的整数由其父进程手机。进程将要返回的值传递给exit( 2)系统调用(或者重main( )函数中返回)

进程的生命周期

进程生命周期.png

僵尸状态:当生命周期超过子进程,但是仍然抛弃自己的子进程转移到其他事情的父进程会使得其子进程处于半死不活的僵尸状态

进程地址空间

用户态的一个优点在于虚拟内存的隔离,进程独享一个私有的地址空间,在iOS 上范围2~3GB,在32为OS X 上为4GB,在64位的OS X 上则为不可想象的16EB

进程内存分配(用户态)

alloca( )

尽管栈在传统上一直都是保存自动变量,但是在某些情况下,程序员也可以选择用栈来动态分配内存,方法是使用鲜为人知的alloca( ) 这个函数的原型和malloc( )是一样的,区别在于这个函数返回的指针是栈上的地址而不是堆中的地址。
从实现角度,alloca( )从两方面优于malloc( )

堆分配

堆是由C语言运行时维护的用户态数据结构,通过堆的使用,程序可以不用直接在页面的层次处理内存分配。Darwin的libC 采用了一个基于分配区域(allocation zone)的特殊分配算法

虚拟内存(系统管理员角度)

页面状态 意义
Free(空闲) 物理页面没有被任何虚拟内存页面使用,如果有的话,可以立即回收
Acitve(活跃) 物理页面当前正用于一个虚拟内存页面,而且最近被引用过。这个页面不太可能被交换出去,除非不再有任何非活跃的物理页面存在了。如果这个页面近期不会被引用,则会被置于非活跃的状态
Inactive(非活跃) 物理页面当前正用于一个虚拟内存页面,但是最近没有被任何进程引用过。这个页面有可能会在有需要时被交换出去,另外,如果这个页面在任何时刻被引用了,那么会被重新置于活跃状态
Speculative(投机) 页面被投机映射。通常产生这个状态的原因是针对可能的内存需求做了一次猜测的分配,但是还没有处于活跃状态(也不是非活跃状态,因为有可能很快被访问)
Wired down(联动) 物理页面当前正用于一个虚拟内存页面。但是不能被交换出去,不论引用状况如何
物理页面的状态迁移.png

线程

线程作为最大化利用进程时间片的方法,应运而生:通过使用多个线程,程序的指向可以分割表面上看上去并发执行的子任务。线程之间切换的开销比较小,只要保存和恢复寄存器即可。多核处理器更是特别和适合线程,因为多个处理器核心共享同样的cache和ARM,这位线程间的共享虚拟内存提供了基础

函数块中的工作由一下几个分发队列中的某一个完成:

GCD的API都声明在<dispatch/dispatch.h>头文件中,代码实现在libDispatch.dylib库中,这是一个libSystem的内部库。这些API本身都是基于preeathed_workqueue API实现的,而XNU通过workq系统调用也支持这个API。要注意的是:Objective-C 进一步封装这些API,暴露给用户的是NSOperation 相关的对象

上一篇 下一篇

猜你喜欢

热点阅读