Linux多线程中fork()调用的相关问题总结

1.某个线程调用fork()函数:

在一个多线程程序中的某个线程调用了fork函数,那么子进程只会拥有一个执行线程(调用fork函数的线程),其他"已经"创建的线程将不会复制给子进程,子进程多线程的情况是在调用fork函数的子线程之后调用pthread_create函数实现的。

2.调用fork函数之后锁的继承:

由fork函数创建的子进程会继承父进程的锁及其状态,但子进程可能不清楚从父进程继承而来的互斥锁的具体状态(是加锁还是解锁状态),这个互斥锁可能被加锁了,但是并不是由调用fork函数的那个线程锁住的,而是由其他线程锁住的。如果是这种情况,则子进程若再次对该互斥锁执行加锁操作就会导致死锁

确保fork调用后父进程和子进程都拥有一个清楚的锁状态的函数是 pthread_atfork;

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

 

  • prepare处理函数由父进程在fork创建子进程前调用,这个函数的任务是获取父进程定义的所有锁 。
  • parent处理函数是在fork创建了子进程以后,但在fork返回之前在父进程环境中调用的。它的任务是对prepare获取的所有锁解锁。
  • child处理函数在fork返回之前在子进程环境中调用,与parent处理函数一样,它也必须解锁所有prepare中所获取的锁。

下面代码并不是加锁一次解锁了两次,而是各自独自解锁。因为prepare函数是在创建子进程之前执行的,因此此时互斥锁是锁住的状态,parent函数执行是在子进程创建之后,其首先是对prepare中锁住的互斥锁解锁,但此时在子进程中任然有一个锁住的互斥锁的副本(fork的写时复制机制),因此需要在child中再次解锁。

需要注意的是pthread_atfork只能清理锁,但不能清理条件变量。在有些系统的实现中条件变量不需要清理。但是在有的系统中,条件变量的实现中包含了锁,这种情况就需要清理。但是目前并没有清理条件变量的接口和方法。

下面是引用别人的一段代码(使用非常清楚):

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<pthread.h>
//使用pthread_atfork函数进行获取锁
pthread_mutex_t mutex;
void *fun(void *arg)
{
	printf("fun will get pthread\n");
	pthread_mutex_lock(&mutex);
	printf("fun mutex locked\n");
	sleep(5);
	pthread_mutex_unlock(&mutex);
	printf("fun mutex unlcok\n");
}
void prepare()   //pthread_atfork一旦被调用就会执行该函数,但是需要等待fun释放锁才可以将锁加上
{
	pthread_mutex_lock(&mutex);
	printf("prepare get mutex\n");
}
void parent()
{
	pthread_mutex_unlock(&mutex);
	printf("parent progress get mutex\n");
}
void child()
{
	pthread_mutex_unlock(&mutex);
	printf("child progress get mutex\n");
}
int main()
{
	pthread_mutex_init(&mutex,NULL);
	pthread_t id;
	int res=pthread_create(&id,NULL,fun,NULL);
	assert(res==0);
	sleep(1);
 
	pthread_atfork(prepare,parent,child);
	if(fork())   //父进程与子进程相当与加了两把不同的锁了,没有什么关系了
	{
		printf("father will get mutex\n");
		pthread_mutex_lock(&mutex);
		sleep(1);
		printf("father lock success\n");
		pthread_mutex_unlock(&mutex);
		printf("father over\n");
	}
	else
	{
		printf("child will get mutex\n");
		pthread_mutex_lock(&mutex);
		printf("child lock success\n");
		sleep(2);
		pthread_mutex_unlock(&mutex);
		printf("child over\n");
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值