日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

【Linux】多线程中使用fork()

發布時間:2023/11/27 生活经验 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux】多线程中使用fork() 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(最核心的東西我在下面用紅色字體標出來了,理解了那塊,這些東西都是就理解了!)

在本篇文章開始之前,需要大家先了解線程和進程,這位大哥講的言簡意賅:進程和線程的主要區別(總結)_kuangsonghan的博客-CSDN博客_進程與線程的區別

如標題所示,如果在多線程中的某一個線程中使用fork函數之后,fork產生的子進程會不會復制父進程中的線程呢?

答案是不會的,fork的時候只復制當前線程到子進程,下面是fork的描述:

fork(2): create child process - Linux man page

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.
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.

下面我們來看一下下面這個例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/wait.h>pthread_mutex_t mutex; //互斥鎖的創建void * fun(void * arg)
{pthread_mutex_lock(&mutex);printf("fun lock \n");sleep(5);pthread_mutex_unlock(&mutex);printf("fun unlock \n");
} int main()
{pthread_mutex_init(&mutex,NULL);pthread_t id;pthread_create(&id,NULL,fun,NULL);sleep(1);pid_t pid = fork();if(pid == -1){exit(0);}if(pid == 0){printf("child will lock \n");pthread_mutex_lock(&mutex);printf("chile lock \n");pthread_mutex_unlock(&mutex);printf("child umlock \n");exit(0);}wait(NULL);printf("main end \n");exit(0);
}

上述代碼中整體的邏輯? 我來給大家理一下,先開始是主線程創建了子線程,然后子線程中啥也不干,加鎖----輸出fun lock------睡眠五秒鐘------解鎖-----輸出fun unlock

等不到子線程執行完,主線程又執行了fork命令,將主線程復制一份到子進程中,這會的主線程也充當了子進程的父進程,因為所有線程共享一把鎖,這會子線程中的鎖還在枷鎖狀態中,所以子進程中也就被fork將鎖的加鎖狀態鎖給復制到了子進程中,

這時候到了子進程中的時候,子進程首先打印出child will lock 然后準備加鎖的時候發現,鎖是夾著的狀態,所以就一直會阻塞在子進程中加鎖的那一步,ok,整體梳理了一遍,我們來看上述代碼的運行結果:

?和我上述理的思路一毛一樣,最后程序一直阻塞到了子進程中加鎖那步,那么這種情況怎么解決呢?

首先我們在fork的時候,我們不清楚鎖的狀態,所以才會造成上面的問題出現,所以我們必須在fork的時候就清楚鎖的狀態:

其實在Linux中人家已經幫我們寫好了,他就是:pthread_atfork

atfork() --同步父子進程 pthread_mutex_lock加解鎖問題_Turbyun的博客-CSDN博客

pthread_atfork(void (*prepare)(void),void (*parent)(void), void(*child)(void))

?該函數中的三個參數都是指向函數的指針

第一個參數是在調用fork之前該調用的函數

第二個參數是在調用fork之后,父進程該調用的函數

第三個參數是在調用fork之后,子進程該調用的函數

ok? ?上述參數也交代清楚了? ?那么在我們上述的代碼中這三個函數分別應該怎么寫那?

在調用fork之前應該調用的函數:對互斥鎖的加鎖

void before_fork()
{pthread_mutex_lock(&mutex);
}

在調用fork之后應該調用的函數:對互斥鎖的解鎖

void after_fork()
{pthread_mutex_unlock(&mutex);
}

這時候 我們已經清楚鎖的狀態了,這種也就是清楚鎖的狀態的時候,fork才會進程執行,也就是推遲fork執行的時間,那么加上代碼之后我們來看總代碼:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/wait.h>pthread_mutex_t mutex; //互斥鎖的創建void before_fork()
{pthread_mutex_lock(&mutex);
}void after_fork()
{pthread_mutex_unlock(&mutex);
}void * fun(void * arg)
{pthread_mutex_lock(&mutex);printf("fun lock \n");sleep(5);pthread_mutex_unlock(&mutex);printf("fun unlock \n");
} int main()
{pthread_mutex_init(&mutex,NULL);pthread_t id;pthread_create(&id,NULL,fun,NULL);sleep(1);pthread_atfork(before_fork,after_fork,after_fork);  //這行代碼只要在fork之前就行pid_t pid = fork();if(pid == -1){exit(0);}if(pid == 0){printf("child will lock \n");pthread_mutex_lock(&mutex);printf("chile lock \n");pthread_mutex_unlock(&mutex);printf("child umlock \n");exit(0);}wait(NULL);printf("main end \n");exit(0);
}

然后執行的時候,fork會等待子線程解鎖之后才執行:

一般來說? 真實的代碼中不會讓子線程中sleep(5)然后再執行fork? ?這只是為了讓我們能看的更清楚,所以才加的,真實的是子線程加鎖解鎖然后fork,是很快的,肉眼根本察覺不到的!

?

“每一個不曾起舞的日子,都是對生命的辜負!”

總結

以上是生活随笔為你收集整理的【Linux】多线程中使用fork()的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。