歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> Unix基礎知識

UNIX環境高級編程:線程和fork

當線程調用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 unsupported\n");  
#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 fork\n");  
    else
      {  
        printf("parent returned from fork\n");  
        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

Copyright © Linux教程網 All Rights Reserved