進程管理

實驗目的

  1. 加深對進程概念的理解,明確進程和程序的區別。
  2. 掌握Linux系統中的進程創建,管理和刪除等操作。
  3. 熟悉使用Linux下的命令和工具,如man, find, grep, whereis, ps, pgrep, kill, ptree, top, vim, gcc,gdb, 管道等。

實驗內容

task1

要求: 打開一個vi進程。通過ps命令以及選擇合適的參數,只顯示名字為vi的進程。尋找vi進程的父進程,直到init進程為止。記錄過程中所有進程的ID和父進程ID。將得到的進程樹和由pstree``命令的得到的進程樹進行比較。

1.首先下載安裝vim,通過sudo apt-get install vim-get實現

image

2.查詢進程可使用pgrep命令來搜索進程名,通過xargs獲取到命令的輸出并傳遞給另外的命令。所以通過pgrep vi | xqrrg ps –l可看到vi進程以及他的相關進程信息。之后通過ps命令逐個查找父進程,直到找到根進程。
由圖中信息可知:vi進程的進程號為:19905 其父進程進程號為:19894,以此類推可查到根進程。
進程關系表:

父進程 進程號 進程名
19894 19905 vi
19889 19894 bash
1523 19889 gnome
1505 1523 upstart
913 1505 lightdm
1 913 ligh
0 1 init spl
image

其中:

F:flag,表示程序的旗標,4表示使用者為超級用戶,1表示使用者為用戶

S:status,表示這個程序的狀態

UID:表示執行者身份

PID:表示進程ID

PPID:表示父進程的ID

C:表示使用的CPU資源百分比

PRI:priority,表示進程的執行優先權,越小表示越早被執行

NI:nice,表示進程可以被執行的優先級的修正數值

ADDR:表示內核函數

SZ:表示占用內存的大小

WCHAN:表示程序是否正在運作當中。“-”表示正在運行
TTY:表示終端機的位置

CMD:表示所下達指令的名稱

3.通過pstree命令得到進程樹。
<img src="https://img-blog.csdnimg.cn/20190316151202650.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc1Mjk1Mw==,size_16,color_FFFFFF,t_70" width="60%">
在進程樹中可以在systemd – lightdm – lightdm – upstart – gnome-terminal – bash – vi 找到vi所在的位置。其中,systemd是一組系統管理命令,取代了init命令成為系統的第一個進程,gnome-terminal為終端的管理進程。

image

問題總結:

1. ps、pstree及top命令辨析
ps:平時比較常用的查看進程的命令,ps 是顯示瞬間進程的狀態,并不動態變化;如果想對進程運行時間監控,需要用 top 工具。
pstree:顯示進程狀態樹,pstree命令可以列出當前的進程,以及它們的樹狀結構。
使用ps命令得到的數據精確,但數據龐大,不易掌握系統整體狀況。pstree命令清晰明了。它能將當前的執行程序以樹狀結構顯示。
top:用來顯示系統當前的進程狀況。是一個動態顯示過程,即可以通過用戶按鍵來不斷刷新當前狀態。如果在前臺執行該命令,它將獨占前臺,直到用戶終止該程序為止。

task2

要求: 編寫程序,首先使用fork系統調用,創建子進程。在父進程中繼續執行空循環操作;在子進程中調用exec打開vi編輯器。然后在另外一個終端中,通過ps –Al命令、ps aux或者top等命令,查看vi進程及其父進程的運行狀態,理解每個參數所表達的意義。選擇合適的命令參數,對所有進程按照cpu占用率排序。

  1. 編寫test.c程序,實現使用fork系統調用,創建子進程。在父進程中繼續執行空循環操作;在子進程中調用exec打開vi編輯器。
    [圖片上傳失敗...(image-696048-1553237084704)]
  2. 編譯運行test.c程序


    image
  3. 在另一個終端使用命令ps -AL查看現有進程信息。
    image

    在進程列表中可以找到vi進程以及該進程的狀態信息
    image
  4. 運用命令ps aux查看內存中運行的程序:
    image

    其中:

USER:進程使用者賬號;
PID:進程ID號;
CPU:進程使用掉的CPU資源百分比;
MEM:進程所占用的物理內存百分比;
VSZ:進程使用掉的虛擬內存量 (Kbytes)
RSS :進程占用的固定的內存量 (Kbytes)
TTY :進程所在終端機(若與終端機無關,則顯示 “?”,tty1-tty6 是本機上面的登入者程序,若為 pts/0 等等,則表示為由網絡連接進主機的程序。
STAT:程序目前的狀態:R (正在運作) S (正在睡眠) T(正在偵測或停止) Z (zombie(疆尸) 程序)
START:進程被觸發啟動的時間;
TIME :進程實際使用 CPU 運作的時間。
COMMAND:進程所屬的指令

  1. 接著使用top命令將所有進程按照cpu占有率進行排序,根據排序結果可見,我創建的test程序因含有死循環fork所以幾乎完全占用了CPU。
    image

task3

要求: 使用fork系統調用,創建如下進程樹,并使每個進程輸出自己的ID和父進程的ID。觀察進程的執行順序和運行狀態的變化。

image

  1. 根據題目要求編寫程序


    image
  2. 多次運行得到如下輸出。可以看出P1為P2和P3的父進程,P2位P4和P5的父進程,與實驗要求的進程樹相同。


    image
  3. 程序流程簡圖


    image

問題總結:

1. linux中的fork()函數
一個進程包括代碼、數據和分配給進程的資源。fork()函數通過系統調用創建與原來進程幾乎完全相同的進程,相當于克隆了一個自己。但如果初始參數或者傳入的變量不同,兩個進程也可以做不同的事。
一個進程調用fork()函數后,系統先給新的進程分配資源,例如存儲數據和代碼的空間。然后把原來的進程的所有值都復制到新的新進程中,只有少數值與原來的進程的值不同。
2. fork()函數特點
fork函數被調用一次,能夠返回兩次,它可能有三種不同的返回值:
1)在父進程中,fork返回新創建子進程的進程ID;
2)在子進程中,fork返回0;
3)如果出現錯誤,fork返回一個負值;
3. 父進程先結束的問題
在實驗過程中會遇到執行程序時子進程與的父進程號不符合“父子關系”。

image

后發現是因為所有的子進程在getppid()的時候父進程已經結束了,得到的是upstart進程的pid=1523。所以在代碼中加入sleep(1);,讓父進程等待一秒鐘再結束,由此可以正確得到進程間的“父子關系”。

task4

要求: 修改上述進程樹中的進程,使得所有進程都循環輸出自己的ID和父進程的ID。然后終止p2進程(分別采用kill -9 、自己正常退出exit()、段錯誤退出),觀察p1、p3、p4、p5進程的運行狀態和其他相關參數有何改變。

  1. 由于需要循環輸出自己的ID和父進程的ID,所以程序邏輯發生變化,重新編寫程序并運行如下。


    image
  2. 運行該程序,可見循環輸出符合進程樹的進程關系。
    image

    通過pstree -p查看程序進程樹,可見符合原題給出的進程樹。
    image
  3. 終止p2進程
  • 采用kill -9 ,刪除進程p2(2077),再次查看進程樹,可見原進程樹上僅有原來的p1,p2,p3。
    image

    原來為p2子進程的p4和p5現在成為upstart的子進程。
    image

    通過命令ps -aux | grep 2077 查看p2進程的信息,可見進程p2的狀態已變成Z(僵死 a defunct (”zombie”) process),成為僵尸進程。
    在這里插入圖片描述
  • 正常退出exit()
    改寫代碼,使得p2通過exit(0);函數退出。
    image

    運行可見到循環的第二輪p2進程便不在,原本是p2子進程的p3和p4成為upstart的子進程。
    image

    查看進程樹,可見原進程樹有p1,p2,p3進程。
    image

    同樣對p2的進程信息查詢,得到結果顯示p2進程狀態為Z,成為僵尸進程。
    image
  • 段錯誤退出
    采用訪問不存在的內存地址的方式產生段錯誤退出。


    image

    編譯運行該程序并查看進程樹,可得到與上文相類似的結果


    image

    原進程樹僅有p1、p2、p3進程,原為p2子進程的p4,p5成為upstart的子進程。
    image

    image

    查詢p2進程信息,可見p2進程狀態變為Z,成為僵尸進程。


    image

    綜合以上可知,這三種方式終止p2進程都會使得p2進程成為僵尸進程。

問題總結:

1 . 辨析STAT表示的行程的狀態
linux的進程有5種狀態:
D:不可中斷 uninterruptible sleep (usually IO)
R:運行 runnable (on run queue)
S:中斷 sleeping
T:停止 traced or stopped
Z:僵死 a defunct (”zombie”) process

2. 段錯誤的產生原因
段錯誤是指訪問的內存超出了系統給這個程序所設定的內存空間。

  1. 訪問不存在的內存地址

void main() {
int *ptr = NULL;
*ptr = 0;
}

  1. 訪問系統保護的內存地址

void main() {
int *ptr = (int *)0;
*ptr = 100;
}

  1. 訪問只讀的內存地址

void main() {
char *ptr = "test";
strcpy(ptr, "TEST");
}

  1. 棧溢出

void main() {
main();
}

實驗總結

本次實驗,我對于fork()函數有了更加深入的認識,也更加熟練地使用linux系統。通過對于進程信息的創建,查詢,終止等操作,對于“進程”的概念也有了更加感性的認識,更好的理解了課上所講的抽象化的概念。遇到不懂的問題和概念,通過上網查資料,咨詢老師同學,學會了更多的專業知識。希望之后能夠繼續加油,做到真正的理解實驗原理。

github代碼地址

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 進程 1.基本描述 進程是處于執行期的程序以及相關的資源總稱。 相關的資源:打開的文件,掛起的信號,內核內部數據,...
    MagicDong閱讀 501評論 0 0
  • 進程管理 進程概念 進程包括: 程序代碼:有時候被稱為文本段 當前活動:通過程序計數器的值和處理器寄存器的內容來表...
    小透明_SAKURA閱讀 882評論 0 0
  • Linux 進程管理與程序開發 進程是Linux事務管理的基本單元,所有的進程均擁有自己獨立的處理環境和系統資源,...
    JamesPeng閱讀 2,508評論 1 14
  • 前言 只有光頭才能變強 回顧前面: 看完這篇Linux基本的操作就會了 Linux用戶和權限管理看了你就會用啦 這...
    Java3y閱讀 737評論 0 8
  • 有時候,我會不自覺地盯著那雙手看。 當她握住菜刀時,大拇指和食指恰似一對愛斗氣的兄弟被锃亮的刀面隔開,你來我往推推...
    拾記閱讀 387評論 12 9