Advanced Programming in UNIX Environment Episode 65

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/myfather103/article/details/79984133

Threads and fork

When a thread calls fork, a copy of the entire process address space is made for the child. Recall the discussion of copy-on-write in Section 8.3. The child is an entirely different process from the parent, and as long as neither one makes changes to its memory contents, copies of the memory pages can be shared between parent and child.

#include <pthread.h>
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

The parent and the child end up unlocking duplicate locks stored in different memory locations, as if the following sequence of events occurred:

1.The parent acquired all its locks.
2.The child acquired all its locks.
3.The parent released its locks.
4.The child released its locks.

We can call pthread_atfork multiple times to install more than one set of fork handlers.

For example, assume that module A calls functions from module B and that each module has its own set of locks. If the locking hierarchy is A before B, module B must install its fork handlers before module A. When the parent calls fork, the following steps are taken, assuming that the child process runs before the parent:

1.The prepare fork handler from module A is called to acquire all of module A’s locks.
2.The prepare fork handler from module B is called to acquire all of module B’s locks.
3.A child process is created.
4.The child fork handler from module B is called to release all of module B’s locks in the child process.
5.The child fork handler from module A is called to release all of module A’s locks in the child process.
6.The fork function returns to the child.
7.The parent fork handler from module B is called to release all of module B’s locks in the parent process.
8.The parent fork handler from module A is called to release all of module A’s locks in the parent process.
9.The fork function returns to the parent.

#include "apue.h"
#include <pthread.h>

pthread_mutex_t lock1=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2=PTHREAD_MUTEX_INITIALIZER;

void prepare(void)
{
    int err;

    printf("preparing locks...\n");
    if((err=pthread_mutex_lock(&lock1))!=0)
        err_count(err,"can't lock lock1 in prepare handler");
    if((err=pthread_mutex_lock(&lock2))!=0)
        err_count(err,"can't lock lock2 in prepare handler");
}

vid parent(void)
{
    int err;

    printf("parent unlocking locks...\n");
    if((err=pthread_mutex_unlock(&lock1))!=0)
        err_count(err,"can't unlock lock1 in parent handler");
    if((err=pthread_mutex_unlock(&lock2))!=0)
        err_count(err,"can't unlock lock2 in parent handler");
}

void child(void)
{
    int err;

    printf("child unlocking locks...\n");
    if((err=pthread_mutex_unlock(&lock1))!=0)
        err_count(err,"can't unlock lock1 in child handler");
    if((err=pthread_mutex_unlock(&lock2))!=0)
        err_count(err,"can't unlock lock2 in child handler");
}

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

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

    if((err=pthread_atfork(prepare, parent,child))!=0)
        err_exit(err, "can't install fork handlers");
    if((err=pthread_creaete(&tid, NULL,thr_fn,0))!=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)
        printf("child returned from fork\n");
    else
        printf("parent return from fork\n");
    
    return 0;
}

pthread_atfork example

猜你喜欢

转载自blog.csdn.net/myfather103/article/details/79984133