美文网首页
RunLoop内部实现逻辑

RunLoop内部实现逻辑

作者: 曼谷第一开膛手 | 来源:发表于2018-08-31 18:28 被阅读83次
814874-501d1867ac25bd11.png 苹果在文档里的说明,RunLoop 内部的逻辑大致如下: 814874-afe637cac6ff7fe5.png

其内部代码整理如下 :
可以看到,实际上 RunLoop 就是这样一个函数,其内部是一个 do-while 循环。当你调用 CFRunLoopRun() 时,线程就会一直停留在这个循环里;直到超时或被手动停止,该函数才会返回。

RunLoop 的底层实现

从上面代码可以看到,RunLoop 的核心是基于 mach port 的,其进入休眠时调用的函数是 mach_msg()。为了解释这个逻辑,下面稍微介绍一下 OSX/iOS 的系统架构。 814874-30b72cdd90475e71.png

苹果官方将整个系统大致划分为上述4个层次:
应用层包括用户能接触到的图形应用,例如 Spotlight、Aqua、SpringBoard 等。
应用框架层即开发人员接触到的 Cocoa 等框架。
核心框架层包括各种核心框架、OpenGL 等内容。
Darwin 即操作系统的核心,包括系统内核、驱动、Shell 等内容,这一层是开源的,其所有源码都可以在opensource.apple.com里找到。

我们在深入看一下 Darwin 这个核心的架构 814874-76220f201937fce2.png

其中,在硬件层上面的三个组成部分:Mach、BSD、IOKit (还包括一些上面没标注的内容),共同组成了 XNU 内核。

XNU 内核的内环被称作 Mach,其作为一个微内核,仅提供了诸如处理器调度、IPC (进程间通信)等非常少量的基础服务。

BSD 层可以看作围绕 Mach 层的一个外环,其提供了诸如进程管理、文件系统和网络等功能。

IOKit 层是为设备驱动提供了一个面向对象(C++)的一个框架。

Mach

本身提供的 API 非常有限,而且苹果也不鼓励使用 Mach 的API,但是这些API非常基础,如果没有这些API的话,其他任何工作都无法实施。在 Mach中,所有的东西都是通过自己的对象实现的,进程、线程和虚拟内存都被称为"对象"。和其他架构不同, Mach的对象间不能直接调用,只能通过消息传递的方式实现对象间的通信。"消息"是 Mach 中最基础的概念,消息在两个端口 (port)之间传递,这就是 Mach 的 IPC (进程间通信) 的核心。

Mach 的消息定义是在头文件的,很简单:

typedef struct {

mach_msg_header_t header;

mach_msg_body_t body;

} mach_msg_base_t;

typedef struct {

mach_msg_bits_t msgh_bits;

mach_msg_size_t msgh_size;

mach_port_t msgh_remote_port;

mach_port_t msgh_local_port;

mach_port_name_t msgh_voucher_port;

mach_msg_id_t msgh_id;

} mach_msg_header_t;

一条 Mach 消息实际上就是一个二进制数据包 (BLOB),其头部定义了当前端口 local_port 和目标端口 remote_port,

发送和接受消息是通过同一个 API 进行的,其 option 标记了消息传递的方向:

mach_msg_return_t mach_msg(

mach_msg_header_t *msg,

mach_msg_option_t option,

mach_msg_size_t send_size,

mach_msg_size_t rcv_size,

mach_port_name_t rcv_name,

mach_msg_timeout_t timeout,

mach_port_name_t notify);

为了实现消息的发送和接收,mach_msg()
函数实际上是调用了一个 Mach 陷阱 (trap),即函数mach_msg_trap(),陷阱这个概念在 Mach中等同于系统调用。当你在用户态调用 mach_msg_trap() 时会触发陷阱机制,切换到内核态;内核态中内核实现的 mach_msg()

函数会完成实际的工作,如下图: 814874-32fd13abee4f8f17.png

RunLoop

的核心就是一个 mach_msg() (见上面代码的第7步),RunLoop 调用这个函数去接收消息,如果没有别人发送 port消息过来,内核会将线程置于等待状态。例如你在模拟器里跑起一个 iOS 的 App,然后在 App 静止时点击暂停,你会看到主线程调用栈是停留在
mach_msg_trap() 这个地方。

苹果用 RunLoop 实现的功能

首先我们可以看一下 App 启动后 RunLoop 的状态:

  1. kCFRunLoopDefaultMode: App的默认 Mode,通常主线程是在这个 Mode 下运行的。

  2. UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响。

  3. UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用。

4: GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到。

5: kCFRunLoopCommonModes: 这是一个占位的 Mode,没有实际作用。

你可以在这里看到更多的苹果内部的 Mode,但那些 Mode 在开发中就很难遇到了。

相关文章

  • RunLoop

    RunLoop思考 讲讲RunLoop,项目中实际应用? RunLoop内部实现逻辑以及数据结构? RunLoop...

  • RunLoop

    讲讲 RunLoop,项目中有用到吗? RunLoop内部实现逻辑? RunLoop和线程的关系? timer 与...

  • 探寻RunLoop的本质

    iOS底层原理总结 - RunLoop 面试题 讲讲 RunLoop,项目中有用到吗? RunLoop内部实现逻辑...

  • iOS RunLoop

    关于 runloop 面试中经常被问到: 讲讲 RunLoop,项目中有用到吗? RunLoop内部实现逻辑? R...

  • iOS-面试题 runloop(夯实基础学习笔记-温故知新3)

    讲讲 RunLoop,项目中有用到吗?runloop内部实现逻辑?runloop和线程的关系?timer 与 ru...

  • RunLoop -- 相关问题的总结

    1、RunLoop在实际场景的应用 RunLoop -- 在实际开发中的应用 2、RunLoop内部实现逻辑 Ru...

  • RunLoop内部实现逻辑

    其内部代码整理如下 :可以看到,实际上 RunLoop 就是这样一个函数,其内部是一个 do-while 循环。当...

  • iOS底层原理总结 - RunLoop

    面试题 讲讲 RunLoop,项目中有用到吗? RunLoop内部实现逻辑? Runloop和线程的关系? tim...

  • 浅谈RunLoop

    面试题 讲讲runloop,项目中有用到吗? runloop内部实现逻辑 runloop和线程的关系 timer和...

  • RunLoop

    面试题 讲讲 RunLoop,项目中有用到吗? RunLoop内部实现逻辑? Runloop和线程的关系? tim...

网友评论

      本文标题:RunLoop内部实现逻辑

      本文链接:https://www.haomeiwen.com/subject/wpdewftx.html