Linux Advance--线程和fork

来源:互联网 发布:医疗大数据公司排名 编辑:程序博客网 时间:2024/04/30 08:32

当线程调用 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");#elseif ((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");elseprintf("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 调用返回给父进程前运行。

1 0
原创粉丝点击