首先我们构建一个死锁
下面的代码是有死锁的代码
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_t mtx1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx3 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx4 = PTHREAD_MUTEX_INITIALIZER;
void* t1_cb(void* arg) {
pthread_mutex_lock(&mtx1);
sleep(1);
pthread_mutex_lock(&mtx2);
printf("t1_cb");
pthread_mutex_unlock(&mtx2);
pthread_mutex_unlock(&mtx1);
}
void* t2_cb(void* arg) {
pthread_mutex_lock(&mtx2);
sleep(1);
pthread_mutex_lock(&mtx1);
printf("t2_cb");
pthread_mutex_unlock(&mtx1);
pthread_mutex_unlock(&mtx2);
}
void* t3_cb(void* arg) {
pthread_mutex_lock(&mtx3);
sleep(1);
pthread_mutex_lock(&mtx4);
printf("t3_cb");
pthread_mutex_unlock(&mtx4);
pthread_mutex_unlock(&mtx3);
}
void* t4_cb(void* arg) {
pthread_mutex_lock(&mtx4);
sleep(1);
pthread_mutex_lock(&mtx1);
printf("t4_cb");
pthread_mutex_unlock(&mtx1);
pthread_mutex_unlock(&mtx4);
}
int main(void) {
pthread_t t1, t2, t3, t4;
pthread_create(&t1, NULL, t1_cb, NULL);
pthread_create(&t2, NULL, t2_cb, NULL);
pthread_create(&t3, NULL, t3_cb, NULL);
pthread_create(&t4, NULL, t4_cb, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
pthread_join(t4, NULL);
printf("complete\n");
return 0;
}
创建死锁检测工具
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#define _GNU_SOURCE
#include <dlfcn.h>
void before_lock(pthread_t tid, pthread_mutex_t* mtx) {
// 查下线程和锁的关系表,看看对应的锁是否被某个线程占用了
// 如果没有,正常进行
// 如果有,在有向图中构建当前自己的线程指向占用这个锁的线程的一条边 self -> tid
}
void after_lock(pthread_t tid, pthread_mutex_t* mtx) {
// 在线程和锁的关系表中增加一条锁和线程的关系
// 有向图中删除一条边
}
void after_unlock(pthread_t tid, pthread_mutex_t* mtx) {
// 从线程和锁的关系表中删除一条锁和线程的关系
}
typedef int (*pthread_mutex_lock_t)(pthread_mutex_t *mtx);
pthread_mutex_lock_t pthread_mutex_lock_f = NULL;
typedef int (*pthread_mutex_unlock_t)(pthread_mutex_t *mtx);
pthread_mutex_unlock_t pthread_mutex_unlock_f = NULL;
int pthread_mutex_lock(pthread_mutex_t *mtx) {
printf("before pthread_mutex_lock %ld, %p\n", pthread_self(), mtx);
pthread_mutex_lock_f(mtx);
printf("after pthread_mutex_lock\n");
}
int pthread_mutex_unlock(pthread_mutex_t *mtx) {
pthread_mutex_unlock_f(mtx);
printf("after pthread_mutex_unlock %ld %p\n", pthread_self(), mtx);
}
void Init_hook(void) {
if (!pthread_mutex_lock_f) {
// dlsym函数用于从动态库中获取symbol地址。
// RTLD_NEXT表示从当前动态库加载器加载的下一个动态库中查找。
// "pthread_mutex_lock"是要查找的函数名。
// dlsym成功后会返回函数地址,赋值给pthread_mutex_lock_f指针变量。
pthread_mutex_lock_f = dlsym(RTLD_NEXT, "pthread_mutex_lock");
}
if (!pthread_mutex_unlock_f) {
pthread_mutex_unlock_f = dlsym(RTLD_NEXT, "pthread_mutex_unlock");
}
}
pthread_mutex_t mtx1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx3 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx4 = PTHREAD_MUTEX_INITIALIZER;
void *t1_cb(void *arg) {
pthread_mutex_lock(&mtx1);
sleep(1);
pthread_mutex_lock(&mtx2);
printf("t1_cb");
pthread_mutex_unlock(&mtx2);
pthread_mutex_unlock(&mtx1);
}
void *t2_cb(void *arg) {
pthread_mutex_lock(&mtx2);
sleep(1);
pthread_mutex_lock(&mtx1);
printf("t2_cb");
pthread_mutex_unlock(&mtx1);
pthread_mutex_unlock(&mtx2);
}
void *t3_cb(void *arg) {
pthread_mutex_lock(&mtx3);
sleep(1);
pthread_mutex_lock(&mtx4);
printf("t3_cb");
pthread_mutex_unlock(&mtx4);
pthread_mutex_unlock(&mtx3);
}
void *t4_cb(void *arg) {
pthread_mutex_lock(&mtx4);
sleep(1);
pthread_mutex_lock(&mtx1);
printf("t4_cb");
pthread_mutex_unlock(&mtx1);
pthread_mutex_unlock(&mtx4);
}
int main(void) {
Init_hook();
pthread_t t1, t2, t3, t4;
pthread_create(&t1, NULL, t1_cb, NULL);
pthread_create(&t2, NULL, t2_cb, NULL);
pthread_create(&t3, NULL, t3_cb, NULL);
pthread_create(&t4, NULL, t4_cb, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
pthread_join(t4, NULL);
printf("complete\n");
return 0;
}