1.描述一下進程的三個狀態,以及相互轉換
就緒態:進程所需的資源已經全部準備好,等待系統調度進入執行態。
執行態:進程佔用CPU資源運行進程,進程運行結束或時間片用盡或缺少資源時會退出執行態
等待態:進程需要資源沒有全部就緒,進程進入等待態進行等待,當所有資源全部就緒時進入就緒態。
進程狀態轉換:
2.進程控制塊 PCB
PCB(Progress Control Block:進程控制模塊)
PCB是OS進行進程管理的工具,每個進程在被創建時,都會開闢一段內存空間存放與此進程相關的PCB結構。
PCB是操作系統中最重要的記錄型數據結構,它記錄了用於描述進程進展情況以及控制進程運行所需的全部信息。
PCB是進程存在的唯一標誌,在Linux系統中PCB存放在task_struct結構體中。
2.描述一下守護進程、孤兒進程、殭屍進程的概念
孤兒進程:如果父進程先退出,子進程還沒退出,那麼子進程將被init進程收養,這時子進程的父進程就是init進程(1號進程),並由init進程完成對他們的狀態收集工作。
殭屍進程:進程終止後不會立刻消失,而是進入僵死狀態(zombie),直到告知父進程自己終止後,才能完全消失。如果一個進程已經終止了,但是其父進程還沒有獲取其狀態,那麼這個進程就稱之爲殭屍進程。殭屍進程還會消耗一定的系統資源,並且還保留一些概要信息供父進程查詢子進程的狀態。一旦父進程得到想要的信息,殭屍進程就會徹底結束消失。
守護進程:守護進程(daemon),是一種運行在後臺的特殊進程(也是孤兒進程),它獨立於控制終端 ,並週期性地執行某項任務或等待處理某些發生的事件,僅在系統關閉時才終止。 守護進程可以由一個普通的進程按照守護進程的特性改造而來。其改造過程如下:
3.使用fork函數得到的子進程是父進程的一個複製品, 它從父進程處繼承了哪些東西?
子進程從父進程處繼承了整個進程的地址空間,地址空間包括:
進程上下文,進程堆棧,打開的文件描述符,信號控制設定,進程優先級,進程組號等等。
4.例02_fork_3.c、例04_waitpid.c、例05_atexit.c三個進程的代碼截圖及運行結果截圖
fork_3.c:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
pid_t pid;
int length = 0;
char buf[] = "a write to stdout\n";
length = write(1, buf, strlen(buf));
if(length != strlen(buf))
{
printf("write error\n");
}
printf("before fork\n");
pid = fork();
if(pid < 0)
{
perror("fork");
}
else if(pid == 0){
printf("in son process\n");
}else{
sleep(1);
printf("in father process\n");
}
return 0;
}
解釋:
-
當以交互模式運行程序時,是行緩衝,所以"before fork\n"在執行fork前就已經被清空。而其他方式運行程序時則都是全緩衝
-
由於寫入文件的緩衝方式是全緩衝,所以在打印"before fork\n"的時候並沒有清空緩衝區,fork函數在執行時,將緩衝區的內容一起復制給了子進程,所以子進程緩衝區內也有"before fork\n"內容,在這兩個程序結束時。進行清空緩衝區操作,都輸出了"before fork\n"內容。
-
write函數是系統調用,不帶緩衝。
waitpid.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
pid_t pid;
pid=fork();
if(pid < 0)
perror("fork");
if(pid == 0)
{
int i = 0;
for(i=0;i<5;i++)
{
printf("this is son process\n");
sleep(1);
}
_exit(2);
}
else
{
waitpid(pid, NULL, 0);
printf("this is father process\n");
}
return 0;
}
解釋:等待指定子進程結束。
atexit.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void clear_fun1(void)
{
printf("perform clear fun1 \n");
}
void clear_fun2(void)
{
printf("perform clear fun2 \n");
}
void clear_fun3(void)
{
printf("perform clear fun3 \n");
}
int main(int argc, char *argv[])
{
atexit(clear_fun1);
atexit(clear_fun2);
atexit(clear_fun3);
printf("process exit 3 sec later!!!\n");
sleep(3);
return 0;
}
解釋:存放清理函數的空間類似於棧,所以後註冊函數在退出時會先執行。