XNU内核设计--基础篇
作者:FloatingGuy 转载请注明出处:https://floatingguy.github.io/
《深入解析MAC OS X & iOS 操作系统》- 第 二 章: 合众为一:OSX & iOS 使用的技术
重点知识
本章重点介绍 架构设计原则 和 基础模块构建。
架构采用4层架构: 用户体验层 –> Darwin。
基础模块: 突出架构中的核心;会从4层架构中抽取来介绍的模块: Darwin、bundle、应用 APP、用户体验层–Aqua/QuickLook/Spotlight 等。
OSX & iOS框架设计
IOS/OSX 4层架构.
上面3 层闭源,Darwin 是开源的。
darwin 的层次 && 架构
- 层次
darwin -> xnu (混合内核) -> bsd (POSIX标准) -> mach (微内核) + iokit 组件
- 架构
Object-C 编写的 app 只需 要使用框架Cocoa的 接口。
组件/模块
组件中也包含了框架,因为每个组件自身存在框架,并且组件之间的联系也是系统框架(指 OSX/iOS系统)的一部分。
用户体验层
主要包括一下组件(介绍 osx+ios 对应的组件):
- Aqua
- Quick look
- spotlight
- Accessibility 选项
Aqua – OSX GUI
有2条流水线 (是顺序执行的关系):
【1】开启GUI
由launchd 启动 -> WindowServer -> …-> CGXServer fork 子进程
【2】启动交互式登录
launchd -> LoginWindow 进程
模块所在 路径/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Resources/WindowServer
Quick look – 预览
采用插件扩展架构,大部分工作由插件完成。
插件的文件格式 后缀.qlgenerator的 bundle.
插件的组成:特殊编译的二进制程序 + 配置文件
特殊编译的二进制程序 的入口点不是 main 而是 QuickLookGeneratorPluginFactory 入口点。
配置文件:将 插件和对应的文件类型关联起来。
文件类型 是什么?
UTI (Uniform Type Identifier)? 逆 DNS 表示法?
quicklookd “QuickLook 服务器”, 通过 /System/Library/。。。。/com.apple.quicklook.plist 文件在登录时启动。
工具:
qlmanage 插件管理工具,控制后台服务。
使用工具
qlmanage -m
qlmanage 显示 管理的插件(入口,文件,版本)
spotlight – 快速搜索工具
其核心是一个 mds 索引服务器,记录了系统所有文件(支持的文件类型)的 元数据。
在 创建、修改 和删除 事件发生时,内核通知 mds。 通知机制是 fsevents。
mds 负责接受消息,具体干活的是 mdworker 进程,负责将各种元数据信息导入数据库。
mdworker 可以加载 spotlight importer 导入器从文件中 提取元数据。
导入器 有系统提供的在 /System/Library/Spotlight 目录,也有用户自定义的在/Library/Spotlight/。
演示 使用 xcode 创建 spotlight 导入器工程
工具:
- mdutil
- mdfind
- mdimport
- mdls
- mdcheckschema
- mddiagnose
Darwin – UNIX 核心
OSX 开启 ssh
通过修改 /System/Library/LaunchDaemons 中的 plist (ssh.plist),将 Disabled 设置为 false.
ios 需要越狱后 单独安装 ssh, 并且默认有2个用户,root 和 mobile 。 root 默认密码 alpine。
HFS+ 文件系统
此文件系统 可以细分为4个类型:
- 大小写敏感:此时 采用 HFSX 文件系统,是 iOS 上默认的文件系统。
- 不敏感:OSX 采用此类 文件系统
- 支持日志功能:此时 采用 JHFS 文件系统,日志文件系统 通过一个日志记录文件 系统任务执行状态,相当于一个快照,文件系统挂载时 可以去查找 日志。
- 不支持日志功能:
从类型名称 就可以知道其区别,注意 大小写敏感文件系统显示 和 访问时的现象。
显示:不管大小写是否 敏感,都采用创建时的方式显示。
访问:大小写不敏感就可以 随意使用 大小写 。比如 LS/ETC 。。命令, 铭感的文件系统 就要区分大小写。
开发时是使用的 API 并不是 HFS+文件系统直接提供,而是由 虚拟文件交换系统 VFS 提供。VFS 是内核中使用的所有文件系统的统一接口。
VFS 的特性:同时支持 UNIX 文件系统和 外部文件系统。
UNIX 系统目录
OSX 中 UNIX 的目录
|
|
OSX 中 特殊的目录
|
|
iOS 中 目录 & 与 OSX 的目录区别
iOS 内核镜像和 OSX 的区别:
除了上面介绍的文件系统的区别,内核镜像上也存在差异。
iOS 的内核以 kernelcache 的形式将内核扩展 打包在内核中。(kernelcache 在/System/Library/Caches/com.apple.kernelcaches中)。
iOS 内核缓存是加密的 Img3文件。
相关章节:
5、18 章
bundle
bundle 在 OSX 中有多种解释,不再只是 一种文件格式类型,bundle 同时表示一种 目录结构(也称为”包 (package)”)。
bundle 在 OSX 中应用在: 框架、插件、widget、内核扩展中,这些组件都被打包成 bundle。
bundle 中包含了 代码、配置文件(plist)、资源文件。
应用程序和 app
GUID 目录名??
在 iOS app 运行时会被 chroot 到自己的应用目录下 – 名字为GUID的目录–并且不能逃脱这个目录访问文件系统的其他目录。
应用程序会将 自己GUID名字的目录当做根目录,因此需要创建临时目录时,/tmp 指向 GUID/tmp.
ios app 标准目录下的文件/目录 | 用途 |
---|---|
Documents | 应用数据 |
iTunesArtwork | app 的图标,一般是 JPG 文件 |
iTunesMetaData.plist | app的属性列表文件,二进制的 plist 文件 |
Library/ | 杂项文件,包括 Caches、Cookies、Preferences、WebKit |
tmp | 临时文件目录 |
OSX 上的应用格式
非常标准的 bundle 格式存储文件
iOS 应用格式
混乱的 app 格式。ll ~/Music/iTunes/iTunes\ Media/Mobile\ Applications
从 APP Store 下载应用时,应用以.ipa 文件的形式打包–实际就是 zip 文件。
info.plist 文件
首先 介绍这个最重要的文件, 此文件相当于 android apk 里的 Manifest.xml。
此文件 记录了 bundle 的配置信息、依赖关系和其他属性。
plist 文件的格式,系统支持3种格式的 plist。分别是:XML/JSON/二进制格式–BPlists。
除了 JSON使用的较少,其他2种较常见。
工具:plutil 可以将 plist 转换成 不同的格式。plutil -convert xml1 --o - <Info.plist> output.Info.plist
plist 的内容(p28):
Key | 描述/Value |
---|---|
CFBundleDisplayName | 显示给用户的 Bundle 名称 |
。。 | 。。 |
列表中所有的 key 都是 CF 开发,表示这些 key 由 Core Foundation框架定义并处理。
类似的:Cocoa app 包含 NS 开头的 key, NSxxx定义的功能包括:是否允许脚本操作、Java需要、系统偏好设置等等。大部分 NSxxx 只能用于 OSX 不能在 iOS上使用。
其他格式的文件
这些文件在 Resources 目录下。
- NIB 文件, 后缀是.nib。该文件是二进制的 plist 文件,其中保存了应用程序的 GUI 组件的位置和设置信息。
- lproj 文件, 后缀是.lproj。 支持国际化的文件,每种语言对应一个.lproj 的文件。
- icns 图标文件
- CodeResources文件,签过文件。 这是一个符号链接,指向_CodeSignature/CodeResources。此文件包含 bundle 中所有其他文件的列表。 key是文件名,valuse 是文件的 bash64.
加载默认应用程序
当点击一个 文件时,系统会自动使用某个 APP 打开程序。实现文件类型 和默认应用程序的绑定是由 LaunchServices 框架实现(次框架和 launchd 没有关系),此框架是 CoreServices 框架的一部分。
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/
使用 LaunchServices 提供的工具 lsregister 可以查看文件类型的注册信息。cd /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/
./lsregister -dump
|
|
框架
框架也是一种 bundle 格式。框架是不可移植的,是苹果系统特有的。大部分框架是闭源的,框架提供了完整的运行时接口,隐藏底层的系统和库。
框架的内容:
OSX 和 iOS 的 GCC 支持 -framework 选项,此选项可以包含任何依赖的框架(第三方框架+系统框架)。
此选项 可以指向头文件 或者 库文件。
框架搜索路的环境变量:
框架保存的位置:
- /System/Library/Frameworks/ 系统框架
- /Library/Frameworks 第三方框架
- ~/Library/Frameworks 用户提供的框架
重要的框架
- Cocoa: 首选的应用程序编程环境
支持的语言:Object-C, java, AppleSCript。
位置: /System/Library/Frameworks/Cocoa.framework/
此框架依赖于:Foundation、AppKit、CoreData
保护伞框架(umbrella):封装了其他框架的框架。
封装有2种:
- 只是 #import 。 如 Cocoa
- 嵌套了其他框架。 如 Application Service
2.Carbon: OS9 遗留编程接口的名称
MAC OSX 和 iOS的公共框架列表
表2-2 (p35)
库
Mac 包含多套 API 可用。
包括:
- BSD api 方便移植 unix的代码库 (库 Api)
- Mach Trap(Mach 陷阱) OSX 特有的 Api
- 框架 Api
1-2 可以使用C/C++ 开发
3 框架Api 有些必须使用OC开发,比如cocoa, 有些框架可以使用C/C++开发,比如 Carbon
一般框架代码会同时支持cocoa和Carbon, 比如,访问语音合成器的SpeechSynthesis.Framework框架同时位于 ApplicationServices框架(Carbon,C/C++实现)和AppKit(对于Coacoa, OC实现)
系统调用
OSX 的特殊之处在 OSX 的系统调用提供了2套调用接口。
- POSIX 调用
- mach 调用
- POSIX 调用
这是一套 编程标准,专门负责定义API声明(具体到参数类型,格式,返回值,函数名等等)。
当前的POSIX主要分为四个部分:Base Definitions、System Interfaces、Shell and Utilities和Rationale
OSX提供的系统调用,在 系统调用原型继承了POSIX标准,但是 系统编号OSX和标准的编号不同。
在 unistd.h 定义了系统调用原型。
如果系统调用原型和系统编号都一样,那么就可以在多台机型上移植二进制程序(机型必须要支持对应的二进制格式,OSX不支持ELF格式)
BSD 层对 mach做了一次封装。
当前的BSD操作系统变种支持各种通用标准,包括IEEE、ANSI、ISO以及POSIX,同时保持传统BSD的良好风范。
- mach接口
32位,mach系统调用号 是负数, POSIX 的系统调用号时 非负数,所以2者共存。
64位,mach系统调用号 从0x2000000 开头,POSIX以 0x1000000 开头。
总结BSD和mach的系统调用:
32位libSystem.B.dylib库,32位系统调用的指令是 sysenter, 负责系统调用的函数是 __sysenter_trap。
|
|
64 位系统调用的指令是 syscall
|
|
发现不管是32位还是64位除了系统调用号不同,其他的地方没有区别(寄存器使用 和 系统调用命令)
系统调用指令 systenter 具体干什么事?
XNU
xnu 是一个混合内核,xnu由以下几部分构成:
- Mach微内核
- BSD 层
- libKern
- I/O Kit
同时 内核允许动态加载 扩展插件(Kernel Extension , KExt)
Mach
提供了 系统的基本职责, 但是 Mach本身的Api很少。
- 进程和线程的抽象
- 虚拟内存
- 任务调度
- IPC 和 消息传递的机制
BSD
这一层是对Mach 的封装,并且兼容POSIX 标准。包括的内容:
- UNIX 进程模型
- POSIX 线程模型 (Pthread), 同步原语
- UNIX 用户和用户组
- 网络协议栈
- 文件系统访问
- 设备访问 (/dev 下的驱动设备)
libkern
I/O Kit驱动程序 使用C++语言编写。 libkern 库负责提供C++运行时需要的基类。
libkern 是自包含的C++库,提供了C++特性,继承,重载,
I/O kit
I/O Kit 本身就是一套自包含的系统。
个人总结
第二章结束了,对OSX 和iOS 的 架构和 关键组件有了基本认识。同时 对本书的结构有了大体的掌握。
通过分析上面2点已知的内容,可以快速定位 需要的知识,帮助完成突发的工作需求。
第一部分(1-7章) | 第二部分(8-19章) | |
---|---|---|
描述 1 | 分散的知识点 | 系统的知识 |
描述 2 | Apple系统的特色,比如:安全防护技术(3),Mach-O 可执行格式(4),引导过程(6)。 | 内核特性。 |
描述 3 | 还有操作系统中 重要且必备的模块,比如: 进程,调试,启动进程init/Launchd。 | 主要介绍构成 XNU 的4个部分。目前的重点 放在第二部分,重点放在 理解XNU 各部分的代码实现 |
学习的顺序,时间安排,记录的标准。这三个指标需要 动态调整。
注意: 记录重要的代码 位置,功能,函数
Todo:
1. 从xnu开源代码中梳理出这4个部分
Change Log
Time | Change |
---|---|
2017-3-13 | 2.7 节 |
2017-03-14 | 第二章 结束 |
2017-03-14 | 制定 xnu 学习计划 |