fork函数原型与用法
? 在學(xué)習(xí)UNIX編程時(shí),必須要學(xué)習(xí)的一個(gè)函數(shù)為fork函數(shù)。fork函數(shù)也為面試中必定要問的一個(gè)問題,尤其是在BAT的面試中,fork函數(shù)相關(guān)問題更為面試筆試必考知識(shí)點(diǎn)。究其原因:該函數(shù)為UNIX中派生新進(jìn)程的唯一方法。不熟悉fork,就不可能熟悉多線程編程。因此掌握好fork函數(shù),為程序員和準(zhǔn)程序員必備技能。
1、 fork函數(shù)原型
<pre name="code" class="cpp">#include<unistd.h> pid_t fork(void);</span>返回:在子進(jìn)程中返回0,在父進(jìn)程中返回子進(jìn)程的id,出錯(cuò)返回-1.
? 返回:在子進(jìn)程中返回0,在父進(jìn)程中返回子進(jìn)程的id,出錯(cuò)返回-1.
? 如果之前從未接觸過這個(gè)函數(shù),那么理解fork函數(shù)的最困難之處在于調(diào)用它一次,它卻返回兩次。它在調(diào)用進(jìn)程(成為父進(jìn)程)中返回一次,返回值為新派生進(jìn)程(成為子進(jìn)程)的進(jìn)程ID號(hào);在子進(jìn)程中又返回一次,返回值為0.因此,返回值本身告知當(dāng)前進(jìn)程是子進(jìn)程還是父進(jìn)程。
? fork在子進(jìn)程中返回0而不是父進(jìn)程的ID的原因在于:任何子進(jìn)程只有一個(gè)父進(jìn)程,而且子進(jìn)程總是可以通過調(diào)用getppid取得父進(jìn)程的ID。相反,父進(jìn)程可以有許多子進(jìn)程,而且無法獲得各個(gè)子進(jìn)程的進(jìn)程ID。如果父進(jìn)程想要跟蹤所有子進(jìn)程的ID,那么它必須記錄每次調(diào)用fork的返回值。
?父進(jìn)程中調(diào)用fork之前打開所有的描述字在fork返回之后由子進(jìn)程分享。我們將看到網(wǎng)絡(luò)服務(wù)器便利用了這個(gè)特性:父進(jìn)程調(diào)用accept之后調(diào)用fork。所接受的已連接的套接口隨后就在父進(jìn)程與子進(jìn)程之間分享。通常情況下,子進(jìn)程接著讀和寫這個(gè)套接口,父進(jìn)程則關(guān)閉這個(gè)已連接套接口。
2、 fork用法
? fork有兩個(gè)典型的用法:
? 1 一個(gè)進(jìn)程創(chuàng)建一個(gè)自身的拷貝,這樣每個(gè)拷貝都可以在另一個(gè)拷貝執(zhí)行其他任務(wù)的同時(shí)處理各自的某個(gè)操作。這是網(wǎng)絡(luò)服務(wù)器的典型用法。
? 2 一個(gè)進(jìn)程想要執(zhí)行另一個(gè)程序。既然創(chuàng)建新進(jìn)程的唯一方法為調(diào)用fork,該進(jìn)程于是首先調(diào)用fork創(chuàng)建一個(gè)自身的拷貝,然后其中一個(gè)拷貝(通常為子進(jìn)程)調(diào)用exec把自身替換成新的程序。這是諸如shell之類程序的典型用法。
? 3 exec函數(shù)
? 存放在硬盤上的可執(zhí)行文件能夠被UNIX執(zhí)行的唯一方法是:由一個(gè)現(xiàn)有進(jìn)程調(diào)用六個(gè)exec函數(shù)中的某一個(gè)。exec把當(dāng)前進(jìn)程映像替換成新的進(jìn)程文件,而且該新程序通常從main函數(shù)處開始執(zhí)行。進(jìn)程ID并不改變。我們稱調(diào)用exec的進(jìn)程為調(diào)用進(jìn)程,稱新執(zhí)行的程序?yàn)樾鲁绦颉?/p>
六個(gè)exec函數(shù)的區(qū)別在于:
(a)待執(zhí)行的程序文件是由文件名還是由路徑名指定;
(b)新程序的參數(shù)是一一列出還是由一個(gè)指針數(shù)組來引用;
(c)把調(diào)用進(jìn)程的環(huán)境傳遞給新程序還是給新程序指定新的環(huán)境。
|#include<unistd.h> |int execl(const char *pathname, const char *arg0,.../* (char *)0 */); |int execv(const char *pathname, char *const argv[]); |int execle(const char *pathname, const char *arg0,.../* (char *)0,char *const envp[] */); |int execve(const char *pathname, char *const argv[], char *const envp[]); |int execlp(const char *filename, const char *arg0,.../* (char *)0 */); |int execvp(const char *filename, char *const argv[]); | 所有六個(gè)函數(shù)返回:-1——失敗,無返回——成功
? 這些函數(shù)只在出錯(cuò)時(shí)才返回到調(diào)用者。否則,控制將傳遞給新程序的起始點(diǎn),通常就是main函數(shù)。
?這六個(gè)函數(shù)之間的關(guān)系如下圖所示。一般來說,只有 execve 是內(nèi)核中的系統(tǒng)調(diào)用,其他五個(gè)都是調(diào)用 execve 的庫函數(shù)。
注意這六個(gè)函數(shù)的下列區(qū)別:
? 1 頂行三個(gè)函數(shù)把新程序的每個(gè)參數(shù)字符串指定成exec的一個(gè)獨(dú)立參數(shù),并以一個(gè)空指針結(jié)束可變數(shù)量的這些參數(shù)。底行三個(gè)函數(shù)都有一個(gè)作為exec參數(shù)的argv數(shù)組,其中含有指向新程序各個(gè)參數(shù)字符串的所有指針。既然沒有指定參數(shù)字符串的數(shù)目,這個(gè)argv數(shù)組必須含有一個(gè)用于指定其末尾的空指針。
? 2 左列兩個(gè)函數(shù)指定一個(gè)filename參數(shù)。exec將使用當(dāng)前的PATH環(huán)境變量把該文件名參數(shù)轉(zhuǎn)換為一個(gè)路徑名。然而如果這兩個(gè)函數(shù)的filename參數(shù)中不論何處含有一個(gè)斜杠(/),PAHT變量就不再使用。右兩列四個(gè)函數(shù)指定一個(gè)全限定的pathname參數(shù)。
? 3 左兩列四個(gè)函數(shù)不顯式指定一個(gè)環(huán)境指針。相反,他們使用外部變量environ的當(dāng)前值來構(gòu)造一個(gè)傳遞給新程序的環(huán)境清單。右列兩個(gè)函數(shù)顯式指定一個(gè)環(huán)境清單,其envp指針數(shù)組必須以一個(gè)空指針結(jié)束。
————————————————
原文鏈接:https://blog.csdn.net/bad_good_man/article/details/49364947
總結(jié)
以上是生活随笔為你收集整理的fork函数原型与用法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《每日一题》NO.23:谈谈对数字集成电
- 下一篇: aTrust项目的相关操作与分享