死锁检测(未实现,只有思路)

56 阅读3分钟

首先我们构建一个死锁

下面的代码是有死锁的代码


#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;
}