加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

UNIX环境高级编程:线程和fork

发布时间:2016-09-28 13:43:04 所属栏目:Unix 来源:站长网
导读:当线程调用fork时,就为子进程创建了整个进程地址空间的副本。子进程通过继承整个地址空间的副本,也从父进程那里继承了所有互斥量、读写锁和条件变量的状态。如果父进程包含多个线程,子进程在fork返回以后,如果紧接着不是马上调用exec的话,就需要清理

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

在子进程内部只存在一个线程,它是由父进程中调用fork的线程的副本构成的。如果父进程中的线程占有锁,子进程同样占有这些锁。问题是子进程并不包含占有锁的线程的副本,所以子进程没有办法知道它占有了哪些锁,并且需要释放哪些锁。

当多线程进程调用fork创建子进程时,Pthreads指定只有那个调用fork的线程在子进程内存在(表示子进程中只有调用线程这个线程)。尽管当从fork调用返回时,只有调用线程在子进程中存在,所有其他的Pthreads线程状态(互斥量、读写锁和条件变量的状态以及线程私有数据键)仍保留为与调用fork时相同的状态。在子进程中,线程拥有与在父进程内相同的状态。

注:fork调用不会影响互斥量的状态。如果它在父进程中被锁住,则它在子进程中被锁!

因为没有调用线程私有数据销毁和清除处理函数,你可能需要担心存储泄漏问题。

1.fork处理器

int pthread_atfork(void (*prepare)(void),void (*parent)(void),void(*child)(void));//返回值:若成功则返回0,否则返回错误编号

Pthreads增加了pthread_atfork ”fork处理器”机制以允许你的代码越过fork调用保护数据和不变量。这与atexit有点类似,后者在一个进程终止时允许程序执行清除操作。

查看本栏目更多精彩内容:http://www.bianceng.cn/OS/unix/

使用pthread_atfork,你需要提供三个独立的处理函数地址。prepare fork处理程序由父进程调用fork创建子进程之前调用,这个fork处理程序的任务是获得父进程定义所有的锁。parent fork处理程序在fork创建了子进程以后,但在fork返回之前在父进程环境中调用,这个fork处理程序的任务是对prepare fork处理程序获得的所有锁进行解锁。child fork处理程序在fork返回之前在子进程环境中调用,与parent fork处理程序一样,child fork处理程序也必须释放parent fork处理程序获得的所有锁。

可以调用pthread_atfork多次注册多组回调函数,这时,回调函数调用的顺序规定如下:

prepare函数调用顺序与它们的注册顺序相反;

parent和child函数的调用顺序与注册顺序相同。

示例代码:

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <signal.h>  
#include <pthread.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 *fn)  
{  
    printf("thread started...n");  
    pause();  
    return 0;  
}  
      
int main(void)  
{  
    pid_t pid;  
    pthread_t tid;  
    //BSD系统和MAC OS系统不支持pthread_atfork  
#if defined(BSD) || defined(MACOS)  
    printf("pthread_atfork is unsupportedn");  
#else  
    pthread_atfork(prepare, parent, child);  
    pthread_create(&tid, NULL, thr_fn, NULL);  
    sleep(2);  
    printf("parent about to fork...n");  
      
    pid = fork();  
    if( 0 == pid )  
        printf("child returned from forkn");  
    else
      {  
        printf("parent returned from forkn");  
        wait(NULL);  
      }  
#endif  
      
    return 0;  
}

运行结果:

huangcheng@ubuntu:~$ ./a.out
thread started...  
parent about to fork...  
preparing locks...  
parent unlocking locks...  
parent returned from fork  
child unlocking locks...  
child returned from fork

作者:csdn博客 ctthuangcheng

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读