Chinaunix首页 | 论坛 | 博客
  • 博客访问: 968689
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-12-16 10:23:32

12.9 threads and fork

一个进程可能建立多个threads,那么当其中一个thread调用fork的时候,有什么效果:

1 只有调用forkthread会出现在child process里面。

2.由于多个thread可能会持有锁,那么当你fork后,可能子进程里面持有该锁的thread并不在子进程里面,那么子进程里的锁状态就处于一种无法控制的状态。

怎么办:我们需要在fork返回之前,将子进程里面的锁的状态设置为一种可以控制的状态,简单的说就是获得锁然后释放锁,这样子进程就可以处理所有的锁了。但是为了不产生race condition,这个操作应该在fork调用开始后,且返回之前就完成。因此使用pthread_atfork函数可以注册一些函数,使我们在调用fork的时候就可以触发相应的handler被调用。

#include

 

int pthread_atfork(void (*prepare)(void), void

(*parent)(void),

                   void (*child)(void));

 

Returns: 0 if OK, error number on failure

一般食用方法:

1Prepare用来在fork建立子进程的copy之前,在父进程的context里面获得锁,例如通过调用pthread_mutex_lock来获得锁

2Parent用来在prepare将锁获得了之后,且fork建立了子进程的copy之后,在父进程的context下释放锁,即调用pthread_mutex_unlock

3. child用来在prepare将所获得之后,且fork建立了子进程的copy之后,在子进程的context下释放锁,即调用pthread_mutex_unlock

4.然后,fork返回。此时,父进程和子进程的锁的状态都是被释放了的状态。

例子代码:

Figure 12.17. pthread_atfork example

#include "apue.h"

#include

 

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(void)

{

    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)

        err_exit(err, "can't install fork handlers");

    err = pthread_create(&tid, NULL, thr_fn, 0);

    if (err != 0)

        err_exit(err, "can't create thread");

    sleep(2);

    printf("parent about to fork...\n");

    if ((pid = fork()) < 0)

        err_quit("fork failed");

    else if (pid == 0) /* child */

        printf("child returned from fork\n");

    else        /* parent */

        printf("parent returned from fork\n");

#endif

    exit(0);

}

运行结果:

  $ ./a.out

    thread started...

    parent about to fork...

    preparing locks...

    child unlocking locks...

    child returned from fork

    parent unlocking locks...

    parent returned from fork

12.10 threads and i/o

Preadpwrite可以将定位操作,和读取/写入操作融合成一个原子操作,因此可以在没有threadsynchronize保护的情况下直接在各个thread里面调用。

阅读(1350) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~