進程狀態,守護進程,孤兒進程,殭屍進程,全緩衝/行緩衝

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;
}


在這裏插入圖片描述

解釋:存放清理函數的空間類似於棧,所以後註冊函數在退出時會先執行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章