iOS线程生命周期的监控
iOS系统通过Core Services层的Foundation框架提供基于OC语言的NSThread和NSOperationQueue类来实现对线程和线程池的管理和使用。同时也提供了一套基于C语言的GCD线程池函数库来支持多线程的处理应用。这些高级的线程类或者函数的内部实现大部分最终都会调用POSIX标准中的pthread线程库中的pthread_xxx系列函数(#include <pthread.h>)来完成线程的创建、运行、暂停、恢复、销毁、结束等操作。用户态下的线程创建通过系统调用到达内核态的BSD层并创建bsdthread对象,而BSD层则调用Mach层的ksthread对象来完成最终线程的创建和调度的。
pthread库中除了提供一系列标准的线程操作API外,还提供了一个用于监控线程创建、运行、结束、销毁的内省函数(单词introspection翻译为内省,但我觉得叫拦截器可能更好一些)。这个函数定义在头文件#include <pthread/introspection.h>
中,函数的签名为:
pthread_introspection_hook_t pthread_introspection_hook_install(pthread_introspection_hook_t hook)复制代码
函数的作用是安装一个回调函数来挂钩线程生命周期的四个过程。因此函数的入参是一个函数指针,返回的则是老的挂钩函数的指针。回调函数是一个格式为pthread_introspection_hook_t类型的函数,其格式定义如下:
typedef void (*pthread_introspection_hook_t)(unsigned int event, pthread_t thread, void *addr, size_t size);复制代码
回调函数的每个参数的意义如下:
event:指定线程所处的状态。
thread: 线程的句柄,每个pthread线程都由一个pthread_t类型句柄来唯一标识。
addr: 为线程分配的栈内存的基地址。
size: 为线程分配的栈内存的尺寸。
上面说的每一个线程有创建、运行、终止、销毁四个状态,而event则是用来表示线程的四种状态的值,它的值是如下枚举结构的某一个值:
enum {PTHREAD_INTROSPECTION_THREAD_CREATE = 1, //创建PTHREAD_INTROSPECTION_THREAD_START, //运行PTHREAD_INTROSPECTION_THREAD_TERMINATE, //终止PTHREAD_INTROSPECTION_THREAD_DESTROY, //销毁
};
复制代码
需要注意的是在内省函数中设置回调挂钩函数后只会监控设置之后的所有线程状态的变化。因此如果我们要监控整个应用生命周期的所有线程的状态时,需要尽可能早的进行回调函数的设置,比如可以在某个类的+load方法中,或者在某个全局C++对象的构造函数中设置等等。
回调挂钩函数中的第二个参数thread是一个类型为pthread_t线程句柄对象,这个对象的结构并没有对外公开。但是因为pthread库已经被苹果开源:opensource.apple.com/source/libp… 。因此我们可以通过线程句柄对象的内部定义来获取关于线程的更多信息。以方便我们能对线程的各种数据进行更加详细的记录。当然这里我们需要考虑到线程句柄的不同版本下的数据成员的问题。
最后我们实现一个简单的在main函数内实现线程监控的代码示例:
#include <pthread/introspection.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>pthread_introspection_hook_t g_oldpthread_introspection_hook = NULL;void mypthread_introspection_hook(unsigned int event, pthread_t thread, void *addr, size_t size)
{__uint64_t threadid;pthread_threadid_np(thread, &threadid);printf("thread_id = %d, addr = %p, size = %d\n", threadid, addr, size);switch (event){case PTHREAD_INTROSPECTION_THREAD_CREATE://dothing ..break;case PTHREAD_INTROSPECTION_THREAD_START://dothing ..break;case PTHREAD_INTROSPECTION_THREAD_TERMINATE://dothing ..break;case PTHREAD_INTROSPECTION_THREAD_DESTROY://dothing ..break;}//记得在最后或者开头调用老的hook函数if (g_oldpthread_introspection_hook != NULL)g_oldpthread_introspection_hook(event, thread, addr, size);
}int main(int argc, char *argv[])
{//注册线程监控的回调函数为mypthread_introspection_hookg_oldpthread_introspection_hook = pthread_introspection_hook_install(mypthread_introspection_hook);@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));}
}复制代码
你可以通过开源代码中对pthread_t类型结构体的定义来获取线程的更多信息,但是要注意线程库的版本信息。
线程监控回调函数中的代码应该尽可能的精简和高效,包括官方的头文件中也有一段说明(实际上是可以被appstore审核通过的):
This should only be used for introspection and debugging tools. Do not rely on it in shipping code.
欢迎大家访问欧阳大哥2013的github地址
iOS线程生命周期的监控相关推荐
- iOS多线程全套:线程生命周期,多线程的四种解决方案,线程安全问题,GCD的使用,NSOperation的使用(上)
2017-07-08 remember17 Cocoa开发者社区 目的 本文主要是分享iOS多线程的相关内容,为了更系统的讲解,将分为以下7个方面来展开描述. 多线程的基本概念 线程的状态与生命周期 ...
- 线程的生命周期_[线程设计]通过观察者模式监控线程生命周期
推荐书籍:<Java高并发编程详解> 一.无法掌控 Thread 的生命周期 在 Java 中线程的实现只有一个,就是 Thread . 下面是启动一个线程的通用代码,如下: 通过 new ...
- 这么说线程生命周期是不是简单了点?
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | 公众号「日拱一兵」 为什么要了解线程的生命周期 ...
- java不同进程的相互唤醒_Java线程生命周期与状态切换
前提 最近有点懒散,没什么比较有深度的产出.刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期.状态切换以及线程的上下文切换等等.编写本文的时候, ...
- 线程基础知识_线程生命周期_从JVM内存结构看多线程下的共享资源
线程生命周期 线程状态 New: 线程创建(new Thread()) Runnable: 线程可运行(thread.start()), 注: 调用start并不一定是运行状态, 可能在等待CPU调度 ...
- 详解Java线程生命周期与状态切换
前提 最近有点懒散,没什么比较有深度的产出.刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期.状态切换以及线程的上下文切换等等.编写本文的时候, ...
- Java线程生命周期与状态切换
前提# 最近有点懒散,没什么比较有深度的产出.刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期.状态切换以及线程的上下文切换等等.编写本文的时候 ...
- 13.7 线程生命周期状态图、线程常用的方法。
package cn.chen.samplethread; import java.lang.*; /* 线程生命周期状态图.线程常用的方法.线程的生命周期:创建状态.等待就绪态.运行状态.阻塞状态. ...
- 【JAVA多线程学习笔记】(1)实现线程的方式 线程生命周期 操作线程的方法
文章目录 两种方式实现线程 继承Thread类 模拟银行叫号的程序 Runnable接口 代码1:(与swing相结合创建gui程序) Thread类的⼏个常⽤⽅法 线程生命周期 操作线程的方法 代码 ...
最新文章
- 采用fdisk在linux进行分区操作
- 为开源软件评级—商业就绪分级(BRR)模型
- GMF Labels
- 判断直线与线段是否相交,相交则输出交点x轴坐标
- windows执行oracle脚本,Windows下通过计划任务执行数据库备份脚本
- Flutter NestedScrollView实现的一个经典滑动折叠头部图片的效果
- python调用命令行获取pid_命令行命令/命令运行时的pid及获取
- Unity调试外部DLL
- Android 系统(112)---Android系统读取 CPU温度(MTK平台)
- 解析含有资源类型的字符串
- log4j.properties配置文件
- 数据结构(java版)学习笔记(二)——线性表之顺序表
- 英特尔12代酷睿处理器强势来袭
- 6.3深度优先遍历和广度优先遍历
- NDB和InnoDB存储引擎比较
- PS_一寸(2.5*3.5cm)照片排列在六寸(4*6)相片纸
- 自用笔记17——泰波那契数列
- TCP加速:腾讯单边拥塞算法TCPA(类似于BBR、锐速)
- 【Java】时间戳与秒、毫秒转化
- Flask操作指南(超级详细)