.操作系統對進程的管理,是通過進程表完成的.進程表中的每一個表項,記錄的是當前操作系統中一個進程的信息.
.進程在系統的唯一標識是PID,PID是一個從1到32768的正整數,其中1一般是特殊進程init,其它進程從2開始依次編號.當用完32768後,從2重新開始.
.一個稱為“程序計數器(program counter, pc)”的寄存器,指出當前占用 CPU的進程要執行的下一條指令的位置
.當分給某個進程的 CPU時間已經用完,操作系統將該進程相關的寄存器的值,保存到該進程在進程表中對應的表項裡面,把將要接替這個進程占用 CPU的那個進程的上下文,從進程表中讀出,並更新相應的寄存器.
二)fork的一個例子:
#include <sys/types.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t pid;
pid=fork();
if(pid<0)
printf("error in fork!");
else if(pid==0)
printf("I am the child process,ID is %d\n",getpid());
else
printf("I am the parent process,ID is %d\n",getpid());
}
gcc test1.c -o test1
debian:/tmp# ./test1
I am the child process,ID is 2723
I am the parent process,ID is 2722
程序分析:
1)pid=fork();
先來看看子進程的表現:
操作系統調用fork()函數創建一個新的進程(子進程),並且在進程表中相應為它建立一個新的表項,
此時子進程得到CPU的調度,它的上下文被換入,占據 CPU,操作系統對fork的實現,使得子進程中fork調用返回0
所以在這個進程中pid=0,這個進程繼續執行的過程中,if語句中 pid<0不滿足,但是pid= =0是true。所以輸出i am the child process...
父進程的表現:
操作系統對fork的實現,使這個調用在父進程中返回剛剛創建的子進程的pid(一個正整數),所以下面的if語句中pid<0,
pid==0的兩個分支都不會執行。所以輸出i am the parent process...
2)對子進程來說,fork返回給它0,但它的pid絕對不會是0,之所以fork返回0給它,是因為它隨時可以調用getpid()來獲取自己的pid
3)fork之後父子進程除非采用了同步手段,否則不能確定誰先運行,也不能確定誰先結束.認為子進程結束後父進程才從fork返回的,這是不對的,fork不是這樣的,vfork才這樣。
4)父進程執行了所有的進程,而子進程只執行了fork()後面的程序,這是因為子進程繼承了父進程的PC(程序計數器).
三)fork的另一個例子:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid1;
pid_t pid2;
pid1 = fork();
pid2 = fork();
printf("pid1:%d, pid2:%d\n", pid1, pid2);
}
gcc test2.c -o test2
./test2
pid1:18938, pid2:0
pid1:0, pid2:0
pid1:18938, pid2:18939
pid1:0, pid2:18940
程序分析:
1)執行test2時,啟動一個進程,設這個進程為P0,PID為xxxxx
2)當執行到pid1 = fork();時,P0啟動了一個進程,設這個進程為P1,它的PID為18938,暫且不管P1.
3)P0中的fork返回18938給pid1,繼續執行到pid2 = fork();此時啟動另一個新的進程,設為P2,P2的PID為18939 ,同樣暫且不管P2.
4)P0的第二個fork返回18939給p2,最後P0的執行結果為pid1:18938, pid2:18939
5)再看P2,P2生成時,P0中的pid1=18938,所以P2中的pid1繼承P0的pid1=18938,而作為子進程pid2=0,P2從第二個fork後開始執行,
最後輸出pid1:18938, pid2:0.
6)回頭看P1,P1中第一條fork返回0給pid1,然後接著執行後面的語句.而後面接著的語句是pid2 = fork();執行到這裡,P1又產生了一個新進程,設為P3,先不管P3.
7)P1中第二條fork將P3的PID返回給pid2,P3的PID為18940,所以P1的pid2=18940。P1繼續執行後續程序,結束,輸出“pid1:0, pid2:18940”.
8)P3作為P1的子進程,繼承P1中pid1=0,並且第二條fork將0返回給pid2,所以P3最後輸出“pid1:0, pid2:0”.
9)所有的進程都執行完畢.
四)vfork與fork的區別
vfork與fork主要有三點區別:
.fork():子進程拷貝父進程的數據段,堆棧段
vfork():子進程與父進程共享數據段
.fork()父子進程的執行次序不確定vfork 保證子進程先運行,在調用 exec 或 exit 之前與父進程數據是共享的,在它調用 exec或 exit 之後父進程才可能被調度運行。
.vfork()保證子進程先運行,在它調用 exec 或 exit 之後父進程才可能被調度運行.如果在調用這兩個函數之前子進程依賴於父進程的進一步動作,則會導致死鎖。
1)先用fork()進行試驗
#include <unistd.h>
#include <stdio.h>
int main(void)
{
pid_t pid;
int count=0;
pid=fork();
count++;
printf("count= %d\n",count);
return 0;
}