linux进程高级属性之安全的fork

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

解决办法:

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

它会注册三个函数: prepare是在fork调用之前会被调用的,parent在fork返回父进程之前调用,child在fork返回子进程之前调用。如果在prepare中加锁所有的互斥量,在parent和child中解锁所有的互斥量,那么在fork返回之后,互斥量的状态就是未加锁。

实例:

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
pthread_mutex_t mutex;
void prepare(void)
{
	pthread_mutex_lock(&mutex);
	printf("this is prepare process!\n");
}
void parent(void)
{
	printf("this is parent process!\n");
	pthread_mutex_unlock(&mutex);
}
void child(void)
{
	printf("this is child process!\n");
	pthread_mutex_unlock(&mutex);
}
void * thread_f(void *arg)
{
	printf("this is thread_f\n");
	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);
	}
	return (void *)0;

}

int main(int argc,char *argv[])
{
	pthread_t ntid;
	int err,num;
	err = pthread_create(&ntid,NULL,thread_f,NULL);
	if(err!=0)
	{
		printf("Creat new thread fail\n");
		return -1;
	}
	pthread_mutex_init(&mutex,NULL);
	pthread_mutex_lock(&mutex);
	sleep(1);
	pthread_mutex_unlock(&mutex);
	pthread_join(ntid,NULL);
	return 0;
}

运行结果:
binge@binge-HP-Compaq:~/my_share/pthread$ gcc -pthread pthread_fork.c
binge@binge-HP-Compaq:~/my_share/pthread$ ./a.out
this is thread_f
this is prepare process!
this is parent process!
parent process
this is child process!
child process!

猜你喜欢

转载自blog.csdn.net/weixin_42039602/article/details/83245831