死锁监测
死锁现象:
CPU占用率100% ->while(1); 或 死锁;
死锁概念: 多个线程相互等待被占有的资源,陷入一种互相阻塞的情况,这就是死锁;
你有没有遇到死锁,如何检测排查了?
如何检测这种在死锁中的环,如果成环,那大概率死锁;(算法: 有向图是否成环)
如果构建有向图?--> 如何通过资源找到对应线程; 如何知道线程想占用的资源?
1、 线程对应线程号; 锁的指针对应一个锁号; 通过关系表,可以查询到两者间的映射关系;表示了线程占用了哪些锁;
2、 如何表示线程想占用哪些锁呢?, 意味着还没lock; 这里就区分处线程下lock之前和lock之后,线程与锁的关系不同;形象的说,加锁前是想要获得的关系,加锁后是已经占用的关系;
hook协程三步骤: 我们使用hook对C的pthread_mutex进行重写,实现锁前逻辑和锁后逻辑
1、定义函数原型;
typedef ssize_t (*read_t)(int fd, void *buf, size_t count);
read_t read_f = NULL;
typedef ssize_t (*write_t)(int fd, const void *buf, size_t count);
write_t write_f = NULL;
2、Hook:拦截
ssize_t read(int fd, void *buf, size_t count) {}
ssize_t write(int fd, const void *buf, size_t count) {
printf("write: %s\n", (const char *)buf);
return write_f(fd, buf, count);
}
3、使用函数原型前必须初始化 Hook
void init_hook(void) {
if (!read_f) {
read_f = dlsym(RTLD_NEXT, "read");
}
if (!write_f) {
write_f = dlsym(RTLD_NEXT, "write");
}
}
设计的根本关系:

其中,我们依靠邻接表 存储有向图, 寻找是否有环;
用锁和线程的关系表 帮助索引锁和对应线程;
在lock前,进行锁前处理,若锁已经被其他线程持有,则添加等待边;
在加锁后,如果当前线程能顺利加完锁,证明该线程应该独占此锁,在关系表中,双向绑定这层关系,并将尝试等待的关系边删除;如果锁未在locklist记录,则创建新记录,持有者为tid;如果有记录,则释放之前的邻接边,并更新锁的线程为当前线程。
在解锁时,类似于futex底层,每个锁的引用计数不为0,则还有线程在等待该锁,那锁不清除。
当前的设计中,每个线程可以同时拥有多把锁,也只能等待一把锁;如当 t1 成功获得 r1 和 r2 后,它在 locklist 中会有两条记录:
| lock_id | 持有者线程 |
| ------- | ----- |
| &r1 | t1 |
| &r2 | t1 |
关键伪代码:
before_lock(pthread tid, uint64_t mutex){
//锁被持有了,在conn_list找到,对当前线程加边,表示等待
int idx = 0;
if((idx = seach_mutex(mutex)) != -1){
tid2 = conn_list[idx].tid;
add_edge(tid, tid2) //链表
}
}
after_lock(pthread tid, uint64_t mutex){
//锁之前被持有了,在conn_list修改关系表,删除当前等待边
//如果没有被持有,说明是新锁,添加进关系表
int idx = 0;
if((idx = seach_mutex(mutex)) != -1){
tid2 = conn_list[idx].tid;
remove_edge(tid, tid2) //链表
conn_list[idx].tid = tid;
}else{//conn_list数组,由于锁本身可以被回收,可能出现空缺,而我们不想移动数组,那就把回收的锁,初始化,后续找这些空位,填充,找不到就是末尾
int idx1 = search_elock();
conn_list[idx1].tid = tid;
conn_list[idx1].lid = mutex;
}
unlock(pthread tid, uint64_t mutex){
//如果没有其他线程等待该所,conn_list数组下消除该关系;置空;
int idx = seach_mutex(mutex);
if( conn_list[idx1].wait_num == 0){
conn_list[idx1].tid = 0;
conn_list[idx1].lid = 0;
}
}

浙公网安备 33010602011771号