linux之pthread_atfork()函数讲解

来源:互联网 发布:js怎么写乘法表 编辑:程序博客网 时间:2024/06/05 04:46
linux之pthread_atfork()函数讲解

#include <pthread.h>
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

pthread_atfork()在fork()之前调用,当调用fork时,内部创建子进程前在父进程中会调用prepare,内部创建子进程成功后,父进程会调用parent ,子进程会调用child。

直接看下代码:
#include <stdio.h>#include <time.h>#include <pthread.h>#include <unistd.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void *doit(void *arg){    printf("pid = %d begin doit ...\n", static_cast<int>(getpid()));    pthread_mutex_lock(&mutex);    struct timespec ts = {2, 0};    nanosleep(&ts, NULL);    pthread_mutex_unlock(&mutex);    printf("pid = %d end doit ...\n", static_cast<int>(getpid()));    return NULL;}void prepare(void){    pthread_mutex_unlock(&mutex);}void parent(void){    pthread_mutex_lock(&mutex);}int main(void){    pthread_atfork(prepare, parent, NULL);    printf("pid = %d Entering main ...\n", static_cast<int>(getpid()));    pthread_t tid;    pthread_create(&tid, NULL, doit, NULL);    struct timespec ts = {1, 0};    nanosleep(&ts, NULL);    if (fork() == 0)    {        doit(NULL);    }    pthread_join(tid, NULL);    printf("pid = %d Exiting main ...\n", static_cast<int>(getpid()));    return 0;}

同样的流程,但在执行fork() 创建子进程之前,先执行prepare(), 将子线程加锁的mutex 解锁下,然后为了与doit() 配对,在创建子进程成功后,父进程调用parent() 再次加锁,这时父进程的doit() 就可以接着解锁执行下去。而对于子进程来说,由于在fork() 创建子进程之前,mutex已经被解锁,故复制的状态也是解锁的,所以执行doit()就不会死锁了。
执行结果如下:
simba@ubuntu:~/Documents/build/debug/bin$ ./deadlock_test2
pid = 4905 Entering main ...
pid = 4905 begin doit ...
pid = 4908 begin doit ...
pid = 4905 end doit ...
pid = 4905 Exiting main ...
simba@ubuntu:~/Documents/build/debug/bin$ pid = 4908 end doit ...
pid = 4908 Exiting main ...

simba@ubuntu:~/Documents/build/debug/bin$ 

可以看到子进程也正常退出了。


0 0