《實驗一進程創(chuàng)建Linux實驗報告》由會員分享,可在線閱讀,更多相關《實驗一進程創(chuàng)建Linux實驗報告(5頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、
實驗一 進程創(chuàng)建
【實驗目的和要求】
1、1.了解進程的概念及意義;
2.了解子進程和父進程;
3.掌握創(chuàng)建進程的方法。
【實驗內(nèi)容】
1、1.子進程和父進程的創(chuàng)建;
? ?2.編寫附件中的程序實例;
? ?3.撰寫實驗報告。
【實驗原理】
1、原型:
#include
pid_t fork(void);
在linux中fork函數(shù)時非常重要的函數(shù),它從已存在進程中創(chuàng)建一個新進程。新進程為子進程,而原進程為父進程。fork函數(shù)創(chuàng)建子進程的過程為:使用fork函數(shù)得到的子進程是父進程的一個復制品,它從父進程繼承了進程的
2、地址空間,包括進程上下文、進程堆棧、內(nèi)存信息、打開的文件描述符、信號控制設定、進程優(yōu)先級、進程組號、當前工作目錄、根目錄、資源限制、控制終端,而子進程所獨有的只有它的進程號、資源使用和計時器等。通過這種復制方式創(chuàng)建出子進程后,原有進程和子進程都從函數(shù)fork返回,各自繼續(xù)往下運行,但是原進程的fork返回值與子進程的fork返回值不同,在原進程中,fork返回子進程的pid,而在子進程中,fork返回0,如果fork返回負值,表示創(chuàng)建子進程失敗。
子進程和父進程繼續(xù)執(zhí)行fork調(diào)用之后的指令。子進程是父進程的副本。例如,子進程獲得父進程數(shù)據(jù)空間、堆和棧的副本。注意,這是子進程所有用的副本。父
3、進程和子進程并不共享這些存儲空間部分。父進程和子進程共享正文段。
2、原型:
#include
pid_t vfork(void);
vfork函數(shù)的調(diào)用序列和返回值與fork相同,但兩者的語義不同。vfork函數(shù)用于創(chuàng)建一個新進程,而該進程的目的是exec一個新程序。vfork不將父進程的地址空間完全復制到子進程中,因為子進程會立即調(diào)用exec,它在父進程的空間中運行。vfork保證子進程先運行,在它調(diào)用exit之后父進程才可能被調(diào)度運行,當子進程調(diào)用這兩個函數(shù)中的任意一個時,父進程會恢復運行。
【程序代碼】
1、1_fork.c
#inc
4、lude
#include
#include
int var = 10;
int main(int argc,char *argv[])
{
pid_t pid;
int num = 9;
pid = fork();
if(pid<0)//fork函數(shù)創(chuàng)建進程失敗!
{
perror("fork");
}
if(pid==0)//子進程
{
var++;
num++;
printf("in son process var
5、= %d,num=%d\n",var,num);
}
else//父進程
{
sleep(1);
printf("in father process var=%d,num=%d\n",var,num);
}
printf("common code area\n");
return 0;
}
2、2_vfork.c
#include
#include
#include
int var = 10;
int main(int argc,char *argv[]
6、)
{
pid_t pid;
int num = 9;
pid = vfork();//創(chuàng)建進程
if(pid<0)
{
perror("vfork");
}
if(pid == 0)
{
var++;
num++;
printf("in son process var=%d,num=%d\n",var,num);
_exit(0);
}
else
{
printf("in father process var=%d,num=%d\n",var,num);
7、}
return 0;
}
【實驗步驟】
一、
1、打開終端,輸入命令gedit 1_fork.c,在1_fork.c文件中輸入1_fork.bmp中的代碼;
2、輸入命令gcc 1_fork.c -o 1_fork,回車后顯示無錯誤;
3、輸入命令:./1_fork運行程序。
二、
1、打開終端,輸入命令gedit 2_vfork.c,在2_vfork.c文件中輸入2_vfork.bmp中的代碼;
2、輸入命令gcc 2_vfork.c -o 2_vfork,回車后顯示無錯誤:
3、輸入命令:./2_vfork運行程序。
【實驗結果】
1、
從上面可以看到
8、兩次的運行結果不一樣。我們知道write函數(shù)是不帶緩存的。因為在fork之前調(diào)用write,所以其數(shù)據(jù)寫到標準輸出一次。但是,標準 I/O庫是帶緩存的。如果標準輸出連到終端設備,則它是行緩存的,否則它是全緩存的。當以交互方式運行該程序時,只得到printf輸出的行一次,其原因是標準輸出緩存由新行符刷新。但是當將標準輸出重新定向到一個文件時,卻得到printf輸出行兩次。其原因是,在fork之前調(diào)用了printf一次,當調(diào)用fork時,該行數(shù)據(jù)仍在緩存中,然后在父進程數(shù)據(jù)空間復制到子進程中時,該緩存數(shù)據(jù)也被復制到子進程中。于是那時父、子進程各自有了帶該行內(nèi)容的緩存。在exit之前的第二個prin
9、tf將其數(shù)據(jù)添加到現(xiàn)存的緩存中。當每個進程終止時,其緩存中的內(nèi)容被寫到相應文件中。
2、
因為我們知道vfork保證子進程先運行,子進程運行結束后,父進程才開始運行。所以,第一次打印的是子進程的打印的信息,可以看到var值變成了11。子進程結束后,父進程運行,父進程首先打印fork調(diào)用返回給他pid的值(就是子進程pid)。以上我們可以看出,vfork創(chuàng)建的子進程和父進程運行的地址空間相同(子進程改變了var 值,父進程中的var值也進行了改變).
【實驗體會】
1、 由fork創(chuàng)建的新進程
10、被稱為子進程(child process)。該函數(shù)被調(diào)用一次,但返回兩次。兩次返回的區(qū)別是子進程的返回值是0,而父進程的返回值則是 新子進程的進程ID。
2、 將子進程ID返回給父進程的理由是:因為一個進程的子進程可以多于一個,所有沒有一個函數(shù)使一個進程可以獲得其所有子進程的進程ID。fork使子進程得到返回值0的理由是:一個進程只會有一個父進程,所以子進程總是可以調(diào)用getppid以獲得其父進程的進程ID(進程 ID ?0總是由交換進程使用,所以一個子進程的進程ID不可能為0)。
3、 vfork與fork一樣都創(chuàng)建一個子進程; vfork和fork之間的另一個區(qū)別是:vfork保證子進程先運行,在它調(diào)用exit之后 父進程才可能被調(diào)度運行。(如果在調(diào)用這兩個函數(shù)之前子進程依賴于父進程的進一步動作,則會導致死鎖)