线程数量监控

26 阅读3分钟

1. Hook黑魔法

RunTime MethodSwizzling

原理:运行时特性,OC的方法调用在底层都是msg_send(id,SEL),这为我们提供了方法交换实现IMP的机会。但C函数在编译连接时就确定了函数指针的地址偏移量。

应用:更多用于性能检测,crash的兼容和上报.

举例:

FishHook

原理:是FaceBook开源的可以动态修改MachO符号表的工具。强大之处是可以Hook系统的静态C函数

总结:

大家都知道 OC 的方法之所以可以 HOOK 是因为它的运行时特性,OC 的方法调用在底层都是 msg_send(id,SEL)的形式,这为我们提供了交换方法实现(IMP)的机会,但 C 函数在编译链接时就确定了函数指针的地址偏移量(Offset),这个偏移量在编译好的可执行文件中是固定的,而可执行文件每次被重新装载到内存中时被系统分配的起始地址(在 lldb 中用命令image List获取)是不断变化的。运行中的静态函数指针地址其实就等于上述 Offset + Mach0 文件在内存中的首地址

既然 C 函数的指针地址是相对固定且不可修改的,那么 fishhook 又是怎么实现 对 C 函数的 HOOK 呢?其实内部/自定义的 C 函数 fishhook 也 HOOK 不了,它只能HOOK Mach-O 外部(共享缓存库中)的函数。fishhook 利用了 MachO 的动态绑定机制(不清楚的同学看这里:MachO 文件结构详解dyld背后的故事&源码分析 ):苹果的共享缓存库不会被编译进我们的 MachO 文件,而是在动态链接时才去重新绑定。苹果采用了PIC(Position-independent code)技术成功让 C 的底层也能有动态的表现:

  • 编译时在 Mach-O 文件 _DATA 段的符号表中为每一个被引用的系统 C 函数建立一个指针(8字节的数据,放的全是0),这个指针用于动态绑定时重定位到共享库中的函数实现。

  • 在运行时当系统 C 函数被第一次调用时会动态绑定一次,然后将 Mach-O 中的 _DATA 段符号表中对应的指针,指向外部函数(其在共享库中的实际内存地址)。

fishhook 正是利用了 PIC 技术做了这么两个操作:

  • 将指向系统方法(外部函数)的指针重新进行绑定指向内部函数/自定义 C 函数。
  • 将内部函数的指针在动态链接时指向系统方法的地址。

这样就把系统方法与自己定义的方法进行了交换,达到 HOOK 系统 C 函数(共享库中的)的目的。

2.线程数监控

方法1

1.task_threads可以获取到整个App的线程数量。

2.+定时器 有性能问题,间隔很久调用

方法2

1."hook"线程生命周期函数,来获得线程的新建跟销毁

2.用锁保证线程安全 dispatch_semaphore

3.## 通过线程状态改变,来改变线程数量

4.# 打印所有线程堆栈

详细看有道笔记