fork多線程進程


問題

在linux系統中,我們都知道fork會產生一個調用進程的復制,創建出一個新的進程,那么如果父進程有多個線程會不會復制父進程的多個線程呢?

解答

使用man fork指令查看手冊其實就能找到答案,關鍵的一段如下

The child process is created with a single thread—the one that
called fork(). The entire virtual address space of the parent is
replicated in the child, including the states of mutexes, condition
variables, and other pthreads objects; the use of pthread_atfork(3)
may be helpful for dealing with problems that this can cause.

其中第一句話翻譯過來就是子進程創建出來時只有一個線程,就是調用fork()函數的那個線程。

驗證

我們可以用如下代碼驗證一下:

#include<pthread.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

void * func1(void * args){
    while(1){
        printf("func1\n");
    }
}

int main(){
    pthread_t tid;
    pthread_create(&tid, NULL, func1, NULL);
    pid_t pid = fork();
    // 子進程
    if(pid==0){
        int t = 5;
        while(t-->0){
            sleep(1);
            printf("child process\n");
        }
    }
    return 0;
}

代碼執行結果如下:

可以看到子進程在等待的時候並輸出"child process"的時候,父進程創建的線程的函數並沒有輸出。

那么如果我們不是在主線程中fork,而是在創建出的線程中fork呢?代碼如下:

#include<pthread.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

void * func1(void * args){
    // fork()出一個子進程
    pid_t pid = fork();
    // 父進程退出
    if(pid > 0) return NULL;
    while(1){
        sleep(1);
        printf("func1:my pid = %d\n", getpid());
    }
}

int main(){
    pthread_t tid;
    pthread_create(&tid, NULL, func1, NULL);
    // 等待fork()完成
    sleep(1);
    while(1){
        sleep(1);
        printf("main :my pid = %d\n", getpid());
    }
    return 0;
}

執行結果如下:

可以看到結果中子進程只執行了fork()時所在的func1函數,而沒有繼續執行main函數中的指令,也證實了fork的子進程中只產生了fork所在的線程,而沒有產生其它線程。

題外

我們注意手冊中的這句話

The entire virtual address space of the parent is replicated in the child, including the states of mutexes, condition variables, and other pthreads objects;

也就是fork的時候會復制鎖的狀態,也就是說如果此時恰好某個鎖被鎖了,那么在fork產生的子進程中也是lock的狀態。

用如下代碼來驗證一下:

#include<pthread.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void * func1(void * args){
    pthread_mutex_lock(&mutex);
    printf("func1\n");
    pthread_mutex_unlock(&mutex);
}

int main(){
    pthread_t tid;
    pthread_create(&tid, NULL, func1, NULL);
    // sleep保證線程加鎖完成才fork
    sleep(1);
    pid_t pid = fork();
    // 子進程
    if(pid==0){
        int t = 5;
        sleep(1);
        while(t--){
            // 子進程請求鎖
            pthread_mutex_lock(&mutex);
            printf("child process\n");
            sleep(1);
            pthread_mutex_unlock(&mutex);
        }
    }
    return 0;
}

程序執行結果:

子進程進入想要鎖的狀態,但是沒有后續輸出,原因就是fork的時候mutex被鎖住了,而子進程把mutex被鎖的狀態復制了,而又沒有其它子線程來釋放鎖,所以一直請求不到鎖阻塞在pthread_mutex_lock函數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM