我在一個二本類院校,對於linux是不在課程範圍的,屬於個人愛好吧。自己學習了一些,操作系統上學期開了,老師很水,就期末最後兩天學了整本書。
上學期去圖書館借了一本《linux內核設計與實現》當時看的是第二版,但是沒有看完,其實收穫還是挺多的。
說回正題,前兩天有個好朋友給我講他們操作系統還有實驗課,當時我就懵了,確實差距大。於是讓他把實驗課題發給我,我想看看。很多隻有做過實驗,才能深刻體會。
編制一段程序,使用系統調用fork( )創建兩個子進程,這樣在此程序運行時,在系統中就有一個父進程和兩個子進程在活動。每一個進程在屏幕上顯示一個字符,其中父進程顯示字符A,子進程分別顯示字符 B和字符C。試觀察、記錄並分析屏幕上進程調度的情況。
設計思路:
進程的出生:
隨着一句fork,一個新進程呱呱落地,但它這時只是老進程的一個克隆。
調用fork創建的子進程,將共享父進程的代碼空間,複製父進程數據空間,此時子進程會獲得父進程的所有變量的一份拷貝。
系統調用fork(),在fork函數調用完,如果創建成功就會返回兩個進程,一個是father進程和一個新的進程son1(fork的一次調用兩次返回)。
fork()返回值意義如下:
=0:在子進程中,表示當前進程是子進程。
>0:在父進程中,返回值爲子進程的id值(唯一標識號)。
-1:創建失敗。
再在返回的father進程裏面調用fork()創建一個新的進程son2.
然後分別在進程打印A,B,C,然後實驗一下。
看看運行結果:
孤兒進程
父進程在子進程結束之前死亡(return或者exit)
在一定時間內,當系統發現孤兒進程時,init進程就收養孤兒進程,成爲它的father,child進程exit後資源回收都又init進程完成。
僵死進程
子進程在父進程之前結束了,但是父進程沒有用wait或waitpid回收子進程
爲了避免child成爲僵死進程,可以人爲的殺死父進程,可以讓其成爲孤兒進程被init接管,但是如果父進程是服務器進程或者一些重要的進程不能立刻被殺死的話,僵死進程就一直存在,影響系統性能,所以爲了避免這種情況,要調用兩次fork(),讓孫子線程成爲工作線程,如果它成爲僵死線程的話,可以殺死它的父進程。
在實驗中,我還設置了一個數count,是爲了實驗fork創建的子進程,每個進程是父進程的一份複製,但是又有自己的空間,每個進程都有自己的變量。
son1創建時,會複製變量count=0,但是count是存在son1的數據段中,所以son1的count和father以及son2擁有不同的地址,每個count是獨立的,不是共用的。
(但是這個程序存在一個問題,就是有兩個子進程但是隻wait( )了一次·,如果有一個子進程返回,wait調用就結束。父進程可能不會回收第二個返回的子進程,所以還是存在僵死進程的問題。可以使用waitpid()函數來指定回收子進程)
#include <stdlib.h>
#include <stdio.h>
int main()
{
int count=1;
int pid1;
printf("Recently pid is %d \n",getpid());
pid1 = fork();
if(pid1<0)
{
printf("error in fork!");
}
else if(pid1==0)
{
count++;
printf("My father'pid is %d I'm son1,my pid is %d B\n",getppid(),getpid());
}
else
{
int pid2=fork();
if(pid2<0)
{
printf("error in fork!");
}
if(pid2==0)
{
count++;
printf("My father'pid is %d I'm son2,my pid is %d C \n",getppid(),getpid());
}
else
{
waitpid(pid1,NULL);
waitpid(pid2,NULL);
count++;
printf("I'm father,my pid is %d, A \n",getpid());
}
}
printf("%d \n",count);
return 0;
}
最後,fork與vfork的區別
1. fork要拷貝父進程的數據段;而vfork則不需要完全拷貝父進程的數據段,在子進程沒有調用exec和exit之前,子進程與父進程共享數據段
2. fork不對父子進程的執行次序進行任何限制;而在vfork調用中,子進程先運行,父進程掛起,直到子進程調用了exec或exit之後,父子進程的執行次序纔不再有限制