线程与fork之pthread_atfork函数

 当线程调用fork函数时,就为子进程创建了整个进程地址空间的副本,子进程通过继承整个地址空间的副本,也会将父进程的互斥量、读写锁、条件变量的状态继承过来。也就是说,如果父进程中互斥量是锁着的,那么在子进程中互斥量也是锁着的(尽管子进程自己还没有来得及lock),这是非常不安全的,因为不是子进程自己锁住的,它无法解锁。

子进程内部只有一个线程,由父进程中调用fork函数的线程副本构成。如果调用fork的线程将互斥量锁住,那么子进程会拷贝一个pthread_mutex_lock副本,这样子进程就有机会去解锁了。或者互斥量根本就没被加锁,这样也是可以的,但是你不能确保永远是这样的情况。

pthread_atfork函数给你创造了这样的条件,它会注册三个函数

int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

prepare是在fork调用之前会被调用的,parent在fork返回(进入)父进程之前调用,child在fork返回子进程之前调用。如果在prepare中加锁所有的互斥量,在parent和child中解锁所有的互斥量,那么在fork返回之后,互斥量的状态就是未加锁。

可以有多个 pthread_atfork函数,这是也就会有多个处理程序(prepare,parent,child)。多个prepare的执行顺序与注册顺序相反,而parent和child的执行顺序与注册顺序相同

/*  DESCRIPTION:	安全的使用fork
 *	prepare  在调用fork之前会被调用
 *	parent   在fork返回父进程之前被调用
 *	child	 在fork返回子进程之前被调用
 */
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void prepare()
{
	pthread_mutex_lock(&mutex);
	printf("I'm prepare\n");
}


void parent()
{
	pthread_mutex_unlock(&mutex);
	printf("I'm parent\n");
}
void child()
{
	pthread_mutex_unlock(&mutex);
	printf("I'm child\n");
}

void *thread_fun(void *arg)
{
	sleep(1);
	pid_t pid;
	pthread_atfork(prepare, parent, child);
	pid = fork();
	if(pid==0)
	{
		pthread_mutex_lock(&mutex);
		printf("child process\n");
		pthread_mutex_unlock(&mutex);
	}
	if(pid>0)
	{
		pthread_mutex_lock(&mutex);
		printf("parent process\n");
		pthread_mutex_unlock(&mutex);
	}
}

int main()
{
	pthread_t tid;
	
	
	if(pthread_create(&tid, NULL, thread_fun, NULL))
	{
		printf("create new thread failed\n");
		return;
	}

	pthread_mutex_lock(&mutex);
	sleep(2);
	printf("main\n");
	pthread_mutex_unlock(&mutex);
	pthread_join(tid, NULL);
	
	pthread_mutex_destroy(&mutex);

	return;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值