BSD相关特性
OS X由BSD衍生而来,具有很多BSD特性,包括:POSIX,系统调用,BSD扩展,BSD强制访问控制层等。
但OS X还增加了很多复杂的功能,比如沙盒机制:每个应用程序被孤立起来,实现安全性。
XNU核心是Mach,但是用户态展现出来的主要接口是BSD接口。OS X和iOS都提供了一组POSIX兼容的系统调用。还提供了一些BSD特有的调用。
OS X和iOS安全机制
代码签名
在确认软件的安全性之前,首先必须对软件的来源进行真实性验证。如果一个程序从网上下载的,那么该程序是恶意软件的风险就特别大,但是,如果能够验证软件的来源,那么风险会大大降低,同时还可以验证程序在传输过程中是否被篡改。
代码签名就是为了实现这个目的。苹果将证书保存在了OS X和iOS的钥匙链中,使得苹果才是唯一具有root权限的实体,而且这些系统钥匙链还能导出。
在OS X中,代码签名是可选的,但是iOS中却是强制的,如果某个未签名的程序被尝试加载,都会导致这个应用程序进程被内核杀掉。
隔离机制(沙盒化)
应用程序都必须在一个独立的隔间中运行,隔间就是一个隔离的环境,在该环境中所有操作都会受到限制。
iOS沙盒的限制:
- 无法突破程序目录之外的位置。因此程序无法知晓系统上安装的其他程序,因为无法访问文件系统。
- 无法访问系统上的其他进程,即使具有同样UID的进程。应用程序会认为自己就是系统上唯一的进程。
- 无法直接使用任何硬件设备,只能通过苹果提供的框架。
- 无法动态生成代码。mmap(2)和mprotect(2)系统调用的底层实现被修改,防止任何可写内存页面设置为可执行的企图。
- 除了用户mobile能执行的操作的一个子集外,无法执行任何其他操作。应用程序根本不可能有root权限。
进程和线程
进程是一个正在执行的程序的实例,是UNIX的一个基本概念。该实例可以通过Process ID(PID)来唯一辨别。尽管同一个可执行程序可以并发启动多个实例,但每一个实例都有一个不同的PID。进程可以属于进程组。进程组的主要作用是让用户可以同时控制多个进程。通常是向一个进程组发送信号控制这些进程,而不是单独发送。
进程还会将和父进程的亲属关系保存在父进程ID中。父进程可以通过fork创建子进程,并且预期子进程会消亡。
UNIX进程生命周期:运行,然后在运行结束后返回一个整数。子进程返回的整数由父进程手机。
线程是操作系统操作的基本单元。线程是一组寄存器的状态,一个进程可以存在多个线程。一个进程内的所有线程都共享虚拟内存空间,文件描述符和各种句柄。进程被抽象成一个或者多个线程的容器保存下来。
多线程的优点:一个线程的状态可以独立于其他线程,当一个线程睡眠时,另一个线程可以被调度到CPU上执行。线程会在可运行、正在运行以及睡眠之间来回切换。
可以通过一个信号,是一个进程停止执行,相当于冻结了进程,同时挂起这个进程所有的线程。
可执行文件
进程是特殊文件在内存中加载得到的结果。这种文件必须使用操作系统能够理解的格式。这样操作系统才能解析这个文件,建立所需要的依赖,初始化运行时环境开始执行。
chmod+x命令将文件标记为可执行文件,但其实并不能保证能执行,因为只是告诉系统这个文件读入内存,然后寻找一个头签名,据此确定精确的可执行格式。这个头签名称为魔数magic,这是预先定义好的,而且通常是任意选择的一个常量值。魔数可以判断二进制格式,如果是支持的格式,则会调用正确的加载器函数。
#!:UNIX脚本和一些解释器使用的格式,主要用于shell脚本。内核寻找#!后面跟着的字符串,然后执行这个字符串表示的命令。
程序崩溃
当进程异常终止时,自动触发Crash Reporter,生成详细的崩溃日志。该机制在进程消亡前进行快速简单的分析,并且在崩溃日志中记录重要的内容。
iOS和OS X中,Crash Reporter日志都保存在用户的library/logs/carshreporter目录或系统的对应目录下。