Linux Advance--线程和fork

本文介绍如何利用pthread_atfork函数设置fork处理程序来管理进程间共享资源的锁状态,确保父进程与子进程正确解锁,避免死锁。文章通过示例程序详细解释了父进程和子进程对重复锁的操作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当线程调用 fork 时,就为子进程创建了整个进程地址空间的副本。子进程通过继承整个地址空间的副本,也从父进程那里继承了所有互斥量、读写锁和条件变量的状态。如果父进程包含多个进程,子进程在 fork 返回之后,如果紧接着不是马上调用 exec 的话,就需要清理锁状态。

要清除锁状态,可以通过调用 pthread_atfork 函数建立 fork 处理程序。

#include <pthread.h>

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

父进程和子进程对在不同内存位置的重复的锁都进行了解锁操作,就好像出现了下列的事件序列:

1、父进程获得所有的锁

2、子进程获得所有的锁

      3、父进程释放它的锁

      4、子进程释放它的锁

下面是例程:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>

pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;

void prepare(void)
{
	printf("preparing locks...\n");
	pthread_mutex_lock(&lock1);
	pthread_mutex_lock(&lock2);
}

void parent(void)
{
	printf("parent unlocking locks...\n");
	pthread_mutex_unlock(&lock1);
	pthread_mutex_unlock(&lock2);
}

void child(void)
{
	printf("child unlocking locks...\n");
	pthread_mutex_unlock(&lock1);
	pthread_mutex_unlock(&lock2);
}

void *thr_fn(void *arg)
{
	printf("thread started...\n");
	pause();
	return 0;
}

int main()
{
	int 		err;
	pid_t 		pid;
	pthread_t 	tid;

#if defined(BSD) || defined(MACOS)
	printf("pthread_atfork is unsupported\n");
#else
	if ((err = pthread_atfork(prepare, parent, child)) != 0) {
		printf("can't install fork handlers: %s\n", strerror(err));
		exit(1);
	}
	err = pthread_create(&tid, 0, thr_fn, 0);
	if (err != 0) {
		printf("can't create thread: %s\n", strerror(err));
		exit(1);
	}
	sleep(2);
	printf("parent about to fork...\n");
	if ((pid = fork()) < 0) {
		printf("fork failed\n");
		exit(1);
	} else if (pid == 0)
		printf("child returned from fork\n");
	else
		printf("parent returned from fork\n");
#endif // defined
    exit(0);
}


程序中定义了两个互斥量,lock1 和 lock2,prepare fork 处理程序获取这两把锁,child fork 处理程序在子进程环境中释放锁,parent fork 处理程序在父进程中释放锁。

运行该程序得到如下输出:


可以看出,parent fork 处理程序在调用 fork 以后运行,child fork 处理程序在 fork 调用返回到子进程之前运行,parent fork 处理程序在 fork 调用返回给父进程前运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值