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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

【Linux系统编程】fork()函数详解

發(fā)布時(shí)間:2024/4/24 linux 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux系统编程】fork()函数详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

00. 目錄

文章目錄

    • 00. 目錄
    • 01. 進(jìn)程創(chuàng)建函數(shù)
    • 02. 父子進(jìn)程結(jié)構(gòu)
    • 03. 父子進(jìn)程地址空間
    • 04. 附錄

01. 進(jìn)程創(chuàng)建函數(shù)

#include <sys/types.h> #include <unistd.h>pid_t fork(void); 功能:用于從一個(gè)已存在的進(jìn)程中創(chuàng)建一個(gè)新進(jìn)程,新進(jìn)程稱為子進(jìn)程,原進(jìn)程稱為父進(jìn)程。 參數(shù):無(wú) 返回值:成功:子進(jìn)程中返回 0,父進(jìn)程中返回子進(jìn)程 ID。pid_t,為無(wú)符號(hào)整型。失敗:返回-1。失敗的兩個(gè)主要原因是:1)當(dāng)前的進(jìn)程數(shù)已經(jīng)達(dá)到了系統(tǒng)規(guī)定的上限,這時(shí) errno 的值被設(shè)置為 EAGAIN。2)系統(tǒng)內(nèi)存不足,這時(shí) errno 的值被設(shè)置為 ENOMEM。

測(cè)試代碼:

#include <stdio.h> #include <unistd.h>int main(void) {//創(chuàng)建一個(gè)子進(jìn)程fork();printf("hello world\n");return 0; }

測(cè)試結(jié)果:


從運(yùn)行結(jié)果,我們可以看出,fork() 之后的打印函數(shù)打印了兩次,這說(shuō)明,fork() 之后確實(shí)創(chuàng)建了一個(gè)新的進(jìn)程,新進(jìn)程為子進(jìn)程,原來(lái)的進(jìn)程為父進(jìn)程。

02. 父子進(jìn)程結(jié)構(gòu)

使用 fork() 函數(shù)得到的子進(jìn)程是父進(jìn)程的一個(gè)復(fù)制品,它從父進(jìn)程處繼承了整個(gè)進(jìn)程的地址空間:包括進(jìn)程上下文(進(jìn)程執(zhí)行活動(dòng)全過(guò)程的靜態(tài)描述)、進(jìn)程堆棧、打開(kāi)的文件描述符、信號(hào)控制設(shè)定、進(jìn)程優(yōu)先級(jí)、進(jìn)程組號(hào)等。子進(jìn)程所獨(dú)有的只有它的進(jìn)程號(hào),計(jì)時(shí)器等(只有小量信息)。因此,使用 fork() 函數(shù)的代價(jià)是很大的。

簡(jiǎn)單來(lái)說(shuō), 一個(gè)進(jìn)程調(diào)用 fork() 函數(shù)后,系統(tǒng)先給新的進(jìn)程分配資源,例如存儲(chǔ)數(shù)據(jù)和代碼的空間。然后把原來(lái)的進(jìn)程的所有值都復(fù)制到新的新進(jìn)程中,只有少數(shù)值與原來(lái)的進(jìn)程的值不同。相當(dāng)于克隆了一個(gè)自己。

實(shí)際上,更準(zhǔn)確來(lái)說(shuō),Linux 的 fork() 使用是通過(guò)寫(xiě)時(shí)拷貝 (copy- on-write) 實(shí)現(xiàn)。寫(xiě)時(shí)拷貝是一種可以推遲甚至避免拷貝數(shù)據(jù)的技術(shù)。內(nèi)核此時(shí)并不復(fù)制整個(gè)進(jìn)程的地址空間,而是讓父子進(jìn)程共享同一個(gè)地址空間。只用在需要寫(xiě)入的時(shí)候才會(huì)復(fù)制地址空間,從而使各個(gè)進(jìn)行擁有各自的地址空間。也就是說(shuō),資源的復(fù)制是在需要寫(xiě)入的時(shí)候才會(huì)進(jìn)行,在此之前,只有以只讀方式共享。

子進(jìn)程是父進(jìn)程的一個(gè)復(fù)制品,可以簡(jiǎn)單認(rèn)為父子進(jìn)程的代碼一樣的。那大家想過(guò)沒(méi)有,這樣的話,父進(jìn)程做了什么事情,子進(jìn)程也做什么事情(如上面的例子),是不是不能實(shí)現(xiàn)滿足我們實(shí)現(xiàn)多任務(wù)的要求呀,那我們是不是要想個(gè)辦法區(qū)別父子進(jìn)程呀,這就通過(guò) fork() 的返回值。

fork() 函數(shù)被調(diào)用一次,但返回兩次。兩次返回的區(qū)別是:子進(jìn)程的返回值是 0,而父進(jìn)程的返回值則是新子進(jìn)程的進(jìn)程 ID。

測(cè)試代碼:

#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h>int main(void) {int i = 0;pid_t pid = -1;//創(chuàng)建子進(jìn)程pid = fork();if (pid < 0){perror("fork"); goto err0;}//子進(jìn)程if (0 == pid){while(1){printf("child process i = %d\n", i); i++;sleep(1);if (10 == i)break;}printf("child process exit..\n");exit(0); }//父進(jìn)程printf("parent process....\n");while(1){printf("parent do thing\n"); sleep(1);}return 0; err0:return 1; }

測(cè)試結(jié)果如下:

通過(guò)運(yùn)行結(jié)果,可以看到,父子進(jìn)程各做一件事(各自打印一句話)。這里,我們只是看到只有一份代碼,實(shí)際上,fork() 以后,有兩個(gè)地址空間在獨(dú)立運(yùn)行著,有點(diǎn)類似于有兩個(gè)獨(dú)立的程序(父子進(jìn)程)在運(yùn)行著。需要注意的是,在子進(jìn)程的地址空間里,子進(jìn)程是從 fork() 這個(gè)函數(shù)后才開(kāi)始執(zhí)行代碼。

一般來(lái)說(shuō),在 fork() 之后是父進(jìn)程先執(zhí)行還是子進(jìn)程先執(zhí)行是不確定的。這取決于內(nèi)核所使用的調(diào)度算法。

03. 父子進(jìn)程地址空間

為驗(yàn)證父子進(jìn)程各自的地址空間是獨(dú)立的 ,代碼如下:

#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h>int main(void) {//父子進(jìn)程之間數(shù)據(jù)段不是共享int val = 88;pid_t pid = -1;//創(chuàng)建子進(jìn)程pid = fork();if (pid < 0){perror("fork"); goto err0;}//子進(jìn)程if (0 == pid){val++;printf("child &val = %p val = %d\n", &val, val);exit(0); }printf("parent &val = %p val = %d\n", &val, val);return 0; err0:return 1; }

測(cè)試結(jié)果如下:

子進(jìn)程修改了val的值,對(duì)父進(jìn)程沒(méi)有影響。

04. 附錄

4.1 參考博客:【Linux系統(tǒng)編程】fork() 函數(shù)詳解

總結(jié)

以上是生活随笔為你收集整理的【Linux系统编程】fork()函数详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。