溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Linux系統(tǒng)如何使用fork命令創(chuàng)建子進(jìn)程執(zhí)行任務(wù)

發(fā)布時(shí)間:2022-01-25 09:28:38 來(lái)源:億速云 閱讀:197 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下Linux系統(tǒng)如何使用fork命令創(chuàng)建子進(jìn)程執(zhí)行任務(wù),希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

fork 系統(tǒng)調(diào)用

要?jiǎng)?chuàng)建一個(gè)進(jìn)程,最基本的系統(tǒng)調(diào)用是 fork:

 # include pid_t fork(void);
 pid_t vfork(void);

調(diào)用 fork 時(shí),系統(tǒng)將創(chuàng)建一個(gè)與當(dāng)前進(jìn)程相同的新進(jìn)程。通常將原有的進(jìn)程稱為父進(jìn)程,把新創(chuàng)建的進(jìn)程稱為子進(jìn)程。子進(jìn)程是父進(jìn)程的一個(gè)拷貝,子進(jìn)程獲得同父進(jìn)程相同的數(shù)據(jù),但是同父進(jìn)程使用不同的數(shù)據(jù)段和堆棧段。子進(jìn)程從父進(jìn)程繼承大多數(shù)的屬性,但是也修改一些屬性,下表對(duì)比了父子進(jìn)程間的屬性差異:

繼承屬性差異
uid,gid,euid,egid進(jìn)程 ID
進(jìn)程組 ID父進(jìn)程 ID
SESSION ID子進(jìn)程運(yùn)行時(shí)間記錄
所打開文件及文件的偏移量父進(jìn)程對(duì)文件的鎖定
控制終端
設(shè)置用戶 ID 和 設(shè)置組 ID 標(biāo)記位
根目錄與當(dāng)前目錄
文件默認(rèn)創(chuàng)建的權(quán)限掩碼
可訪問(wèn)的內(nèi)存區(qū)段
環(huán)境變量及其它資源分配

下面是一個(gè)常見的演示 fork 工作原理的 demo(筆者的環(huán)境為 Ubuntu 16.04 desktop):

 #include #include #include #include int main(void)
 {
  pid_t pid;
  char *message;
  int n;
  pid = fork();
  if(pid把上面的代碼保存到文件 forkdemo.c 文件中,并執(zhí)行下面的命令編譯: $ gcc forkdemo.c -o forkdemo然后運(yùn)行編譯出來(lái)的 forkdemo 程序: $ ./forkdemofork 函數(shù)的特點(diǎn)是 “調(diào)用一次,返回兩次”:在父進(jìn)程中調(diào)用一次,在父進(jìn)程和子進(jìn)程中各返回一次。在父進(jìn)程中返回時(shí)的返回值為子進(jìn)程的 PID,而在子進(jìn)程中返回時(shí)的返回值為 0,并且返回后都將執(zhí)行 fork 函數(shù)調(diào)用之后的語(yǔ)句。如果 fork 函數(shù)調(diào)用失敗,則返回值為 -1。 我們細(xì)想會(huì)發(fā)現(xiàn),fork 函數(shù)的返回值設(shè)計(jì)還是很高明的。在子進(jìn)程中 fork 函數(shù)返回 0,那么子進(jìn)程仍然可以調(diào)用 getpid 函數(shù)得到自己的 PID,也可以調(diào)用 getppid 函數(shù)得到父進(jìn)程 PID。在父進(jìn)程中用 getpid 函數(shù)可以得到自己的 PID,如果想得到子進(jìn)程的PID,唯一的辦法就是把 fork 函數(shù)的返回值記錄下來(lái)。 注意:執(zhí)行 forkdemo 程序時(shí)的輸出是會(huì)發(fā)生變化的,可能先打印父進(jìn)程的信息,也可能先打印子進(jìn)程的信息。vfork 系統(tǒng)調(diào)用vfork 系統(tǒng)調(diào)用和 fork 系統(tǒng)調(diào)用的功能基本相同。vfork 系統(tǒng)調(diào)用創(chuàng)建的進(jìn)程共享其父進(jìn)程的內(nèi)存地址空間,但是并不完全復(fù)制父進(jìn)程的數(shù)據(jù)段,而是和父進(jìn)程共享其數(shù)據(jù)段。為了防止父進(jìn)程重寫子進(jìn)程需要的數(shù)據(jù),父進(jìn)程會(huì)被 vfork 調(diào)用阻塞,直到子進(jìn)程退出或執(zhí)行一個(gè)新的程序。由于調(diào)用 vfork 函數(shù)時(shí)父進(jìn)程被掛起,所以如果我們使用 vfork 函數(shù)替換 forkdemo 中的 fork 函數(shù),那么執(zhí)行程序時(shí)輸出信息的順序就不會(huì)變化了。使用 vfork 創(chuàng)建的子進(jìn)程一般會(huì)通過(guò) exec 族函數(shù)執(zhí)行新的程序。接下來(lái)讓我們先了解下 exec 族函數(shù)。exec 族函數(shù)使用 fork/vfork 創(chuàng)建子進(jìn)程后執(zhí)行的是和父進(jìn)程相同的程序(但有可能執(zhí)行不同的代碼分支),子進(jìn)程往往需要調(diào)用一個(gè) exec 族函數(shù)以執(zhí)行另外一個(gè)程序。當(dāng)進(jìn)程調(diào)用 exec 族函數(shù)時(shí),該進(jìn)程的用戶空間代碼和數(shù)據(jù)完全被新程序替換,從新程序的起始處開始執(zhí)行。調(diào)用 exec 族函數(shù)并不創(chuàng)建新進(jìn)程,所以調(diào)用 exec 族函數(shù)前后該進(jìn)程的 PID 并不改變。exec 族函數(shù)一共有六個(gè): #include int execl(const char *path, const char *arg, ...);
 int execlp(const char *file, const char *arg, ...);
 int execle(const char *path, const char *arg, ..., char *const envp[]);
 int execv(const char *path, char *const argv[]);
 int execvp(const char *file, char *const argv[]);
 int execve(const char *path, char *const argv[], char *const envp[]);函數(shù)名字中帶字母 “l(fā)” 的表示其參數(shù)個(gè)數(shù)不確定,帶字母 “v” 的表示使用字符串?dāng)?shù)組指針 argv 指向參數(shù)列表。 函數(shù)名字中含有字母 “p” 的表示可以自動(dòng)在環(huán)境變量 PATH 指定的路徑中搜索要執(zhí)行的程序。 函數(shù)名字中含有字母 “e” 的函數(shù)比其它函數(shù)多一個(gè)參數(shù) envp。該參數(shù)是字符串?dāng)?shù)組指針,用于指定環(huán)境變量。調(diào)用這樣的函數(shù)時(shí),可以由用戶自行設(shè)定子進(jìn)程的環(huán)境變量,存放在參數(shù) envp 所指向的字符串?dāng)?shù)組中。事實(shí)上,只有 execve 是真正的系統(tǒng)調(diào)用,其它五個(gè)函數(shù)最終都調(diào)用 execve。這些函數(shù)之間的關(guān)系如下圖所示(此圖來(lái)自互聯(lián)網(wǎng)):exec 族函數(shù)的特征:調(diào)用 exec 族函數(shù)會(huì)把新的程序裝載到當(dāng)前進(jìn)程中。在調(diào)用過(guò) exec 族函數(shù)后,進(jìn)程中執(zhí)行的代碼就與之前完全不同了,所以 exec 函數(shù)調(diào)用之后的代碼是不會(huì)被執(zhí)行的。在子進(jìn)程中執(zhí)行任務(wù)下面讓我們通過(guò) vfork 和 execve 函數(shù)實(shí)現(xiàn)在子進(jìn)程中執(zhí)行 ls 命令: #include #include #include #include int main(void)
 {
  pid_t pid;
  if((pid=vfork())把上面的代碼保存到文件 subprocessdemo.c 文件中,并執(zhí)行下面的命令編譯: $ gcc subprocessdemo.c -o subprocessdemo然后運(yùn)行編譯出來(lái)的 subprocessdemo程序: $ ./subprocessdemo

看完了這篇文章,相信你對(duì)“Linux系統(tǒng)如何使用fork命令創(chuàng)建子進(jìn)程執(zhí)行任務(wù)”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI