任督二脈之進程管理(1)

進程生命週期,進程生命週期建立、退出、中止,以及殭屍進程是什麼意思。linux

1、進程的定義數組

進程--線程。進程是資源分配單位;搞清楚進程就是搞清楚進程資源狀況。進程控制塊PCB是OS的通用叫法。task_struct結構體描述進程的資源狀況。以下圖所屬:數據結構

1)*mm描述內存資源ide

2)*fs:文件系統資源函數

3)文件資源:注意與fs的區別,打開文件的fd數組fd_array記錄打開文件的fd工具

4)*signal:該進程的信號處理函數(用戶理解爲多態)spa

5)pid:數量有限操作系統

節選自《linux操做系統原理與應用》:線程

   傳統上,這樣的數據結構(task_struct)叫作進程控制塊PCB。linux中PCB是一個至關龐大的結構體,其域多達80多項,它的全部域按其功能可分爲如下幾類:3d

  • 狀態信息 描述進程的動態變化
  • 連接信息 描述進程的父子關係
  • 各類標識符 用簡單數字對進程進行標識
  • 進程間通訊信息 描述多個進程在同一任務 上的協做工做
  • 時間和定時器信息 描述進程在生命週期內使用CPU時間的統計、計費等信息
  • 調度信息 描述進程優先級、調度策略等信息
  • 文件系統信息 對進程使用文件狀況進行記錄
  • 虛擬內存信息 描述每一個進程擁有的地址空間
  • 處理器環境信息 描述進程的執行環境(處理器的寄存器及堆棧等)

2、pid

1)pid數量有限,因此不能無限建立進程:32位-32768  64位-131072

2)fork炸彈的原理

改寫一下代碼

1 :() #函數定義
2 {
3     :|:&  #調用本身,而後|管道,管道里面也遞歸調用:建立進程,而後&後臺執行
4 }
5 ;  #函數結束
6 :  #調用本身

|是管道,&是後臺執行。

一直在建立進程,把pid耗盡,kill、killall等命令也要建立一個進程執行,可是pid已經耗盡,沒法執行,用戶感受系統死掉。

 3、task_struct管理

1)造成鏈表:最方便,可是進程之間的關係是樹型關係,父子進程關係,pstree命令能夠查看,因此也能夠用樹。

zsh@zsh-vm:~$ pstree
systemd─┬─ModemManager─┬─{gdbus}
        │              └─{gmain}
        ├─NetworkManager─┬─dhclient
        │                ├─dnsmasq
        │                ├─{gdbus}
        │                └─{gmain}
        ├─VGAuthService
        ├─accounts-daemon─┬─{gdbus}
        │                 └─{gmain}
        ├─acpid

 

2)造成樹:這樣能夠反應進程之間的關係,找父子關係比較簡單,可是有時候須要檢索一個進程的pid,好比 kill -2 8934,這種狀況下樹檢索比較慢了。使用哈希能夠快速查找

3)造成哈希

總結:快速遍歷使用鏈表,想查找父子進程用樹,想經過pid快速查找進程用哈希。因此linux裏面這三種數據結構都有,使得各類場景快速達到目的,以空間換時間。

 

4、進程生命週期

1)就緒態:fork出來就是就緒態,linux裏面就緒和運行的狀態標誌是同樣的

2)運行態:linux裏面就緒和運行的狀態標誌是同樣的,時間片用完或者被搶佔進入就緒態

3)睡眠態:等資源就進入睡眠態,等到資源就進入就緒態

4)殭屍態:進程死掉先成爲殭屍,用於描述task_struct及成員尚未消失,可是進程佔用的資源已經消失;須要父進程wait4(waitpid等)等待殭屍才消失(父進程清理子進程)。因此殭屍狀態是很短的。

殭屍態的緣由是父進程能夠獲取子進程的退出碼exit_code,即退出緣由。

例子:殺死子進程,觀察父進程能監控到子進程死亡緣由。

 1 #include <stdio.h>
 2 #include <sys/wait.h>
 3 #include <stdlib.h>
 4 #include <unistd.h>
 5 
 6 int main()
 7 {
 8     pid_t pid, wait_pid;
 9     int status;
10     
11     pid = fork();
12     
13     if(pid == -1)
14     {
15         perror("Cannot create new process");
16         exit(1);
17     } else if (pid == 0)
18     {
19         printf("child process id: %ld\n", (long)getpid());
20         pause();
21         _exit(0);
22     } else 
23     {
24         #if 0 /* define 1 to make child always a zombie */
25         printf("ppid: %d\n", getpid());
26         while(1);
27         #endif
28         do
29         {
30             wait_pid = waitpid(pid, &status, WUNTRACED | WCONTINUED);
31             
32             if(wait_pid == -1)
33             {
34                 perror("cannot using waitpid function");
35                 exit(1);
36             }
37             
38             if(WIFEXITED(status))
39             {
40                 printf("child process exits, status = %d\n", WEXITSTATUS(status));
41             }
42             
43             if(WIFSIGNALED(status))
44             {
45                 printf("child process is killed by signal %d\n", WTERMSIG(status));
46             }
47             
48             if(WIFSTOPPED(status))
49             {
50                 printf("child process is stopped by signal %d\n", WSTOPSIG(status));
51             }
52             
53             if(WIFCONTINUED(status))
54             {
55                 printf("child process resume running...\n");
56             }
57             
58         }while(!WIFEXITED(status) && !WIFSIGNALED(status));
59         
60         exit(0);
61     }
62 }
View Code

kill -9 pid是殺不死殭屍進程的,由於殭屍進程已經死掉了。父進程一直不清理殭屍進程,能夠經過殺死殭屍進程的父進程來清理。

殭屍進程的資源已經釋放,因此不會形成內存泄漏。

工程中觀察進程是否內存泄漏:多點連續採樣法。震盪收斂沒有泄漏,震盪發散(上升)是內存泄漏。

殭屍太多也很差,佔用pid。

5)中止態:人爲中止進程,發送中止信號:1)ctrl+z,做業控制(JC),發送contine信號繼續運行(fg\bg),kill發送信號等;2)GDB調試;

cpulimit工具控制進程的cpu利用率:cpulimit -l 20 -p pid , 20爲容許的cpu利用率,實際結果不會那麼精

確。

 

5、 fork

1)先看一個例子,fork叉子

結果爲打印6個(1*2+2*2):

 

2)fork返回值:子進程返回0,父進程返回子進程的pid。

運行結果:

 父子進程哪一個先跑默認不肯定,可是有內核可調試開關/proc,傾向於讓子進程先跑。

3)子死父清場:linux裏面老是白髮人送黑髮人

4)深度睡眠:必須等到資源才能醒,不響應信號,因此kill -9也殺不死。why?major page fault,代碼段命運命中,還在硬盤,進程就進入深度睡眠,若是響應信號,那麼信號處理函數有可能也在硬盤,沒有載入內存,再次發生page fault,嵌套。中斷響應嗎?中斷是正在執行被中斷,已經睡眠了,怎麼中斷。

時鐘中斷也不能夠喚醒。

淺度睡眠:資源來了醒,信號來了也能夠醒。時鐘中斷能夠喚醒。

 睡眠是內核調用進入,驅動也能夠。用戶態不能夠直接調用睡眠。

答疑:getppid()獲取父進程的pid。

書籍:operating system three piecies 全英文

課後做業代碼地址:

相關文章
相關標籤/搜索