天天看點

Linux__程序概念詳解

程序

程序指正在執行的程式。從核心來說,它是擔當配置設定系統資源(CPU時間,記憶體)的實體。

那程序跟程式有什麼差別呢?從資料和代碼層面看,它們是一樣的,但是程序比程式多了一個東西,那就是描述程序的PCB結構體。

那這個PCB到底有什麼作用呢?

PCB

相信學過作業系統的同學都知道,作業系統作為軟體和硬體的管理者,那作業系統要管理那麼多的程序,而每個程序都有很多的資訊,為了友善管理這些程序資訊,它們被放在一個叫做程序控制塊的資料結構中,我們稱之為PCB。

在Linux中描述程序的結構體叫做task_struct。它是Linux核心的一種資料結構,會被裝載到記憶體裡。

task_ struct内容分類

辨別符(PID) :跟這個程序相關的唯一辨別符,用來差別其他程序

狀态 :如果程序正在執行,那麼程序處于執行狀态。

優先級 :相對于其他程序的優先級。

程式計數器 :程式中即将被執行的下一條指令的位址。

記憶體指針:包括程式代碼和程序相關資料的指針,還有和其他程序共享的記憶體塊的指針。

上下文資料:程序執行時處理器的寄存器中的資料。

I/O狀态資訊:包括顯示的I/O請求,配置設定給程序的I/O裝置(如錄音帶驅動器)和被程序使用的檔案清單。

審計資訊:可包括處理器時間總和,使用的時鐘數總和,時間限制,審計号等。

辨別符(PID)

在Linux下可以使用top指令(相當于windows系統下的任務管理器)可以檢視

Linux__程式概念詳解

也可以使用ps aux指令,可以檢視所有程序,也可以使用ps aux | grep +特定要查找的程序 。(可以使用ps aux | head -1 && ps aux | grep XXX可在第一行顯示對應的屬性)

當然也有可以檢視PID的函數getpid(),檢視父程序的函數getppid()

#include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 int main()
 {
     printf("pid: %d\n",getpid());
     printf("ppid: %d\n",getppid());
 	 return 0;
 }   
           
getpid傳回目前程序辨別,getppid傳回父程序辨別。可以通過ps aux | grep + PID,可以看到所顯示的父程序PID為bash
           

可以通過echo $$ 檢視腳本運作的目前程序的PID

使用ls /proc 指令可以檢視動态目錄,存放的是一些程序的資訊。

通過系統調用建立程序(fork)

如何建立一個程序呢?我們可以使用fork()函數來建立

#include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 int main()
 {
     fork();
     printf("process : %d , parent: %d\n", getpid(), getppid());
     sleep(1);
     return 0;
 }
           
Linux__程式概念詳解

可以看到fork之後有兩個程序,為父子關系。

而fork的有兩個傳回值,給父程序傳回子程序的PID,給子程序傳回0值。 父程序後面需要通過子程序的PID管理子程序的狀态。

程序狀态

可以通過ps aux | ps axj 指令檢視

R(running) 運作狀态:表示程序要麼在運作中,要麼在運作隊列裡。

S(sleeping) 睡眠狀态:可中斷睡眠狀态,表示程序正在等待事件完成。

D(disk sleep) 磁盤休眠狀态:不可中斷睡眠狀态,在這個狀态的程序通常會等待IO的結束。

T(stopped) 停止狀态:可以通過發送 SIGSTOP 信号給程序來停止(T)程序。這個被暫停的程序可 以通過發送 SIGCONT 信号讓程序繼續運作。

X(dead) 死亡狀态:這個狀态為傳回狀态。

Z(zombie) 僵屍狀态:當程序退出并且父程序使用wait()系統調用沒有讀取到子程序退出的傳回代碼時就會産生僵死(屍)程序,僵死程序會以終止狀态保持在程序表中,并且會一直在等待父程序讀取退出狀态代碼。 是以,隻要子程序退出,父程序還在運作,但父程序沒有讀取子程序狀态,子程序進入Z狀态。(類似于警察檢查死者,要知道死者的原因和狀态)

注:若系統中有大量僵屍狀态的程序,長時間不回收,會造成記憶體資源的浪費,造成==記憶體洩漏問題==
           

在下面簡單的實作一個僵死程序

#include <iostream>                                       
#include <stdlib.h>
#include <sys/types.h>
include <unistd.h>
using namespace std;

int main()
{
    pid_t id = fork();
    int count = 0;
    if(id == -1){
        cerr << "fork error " << endl;
    }
    if(id == 0){//chlid
    while(1){
        cout << "I am chlid ..." << endl;
        sleep(1);
        if(count++ >= 3)
             exit(1);   //退出程序
    }
    else
	{
		 while(1){//father
		 cout << "I am father " << endl;
		 sleep(1);
		 }
	}
	return 0;
}

           

另起一個終端,跑一個腳本 while :; do ps aux | grep ‘myprocess’| grep -v grep ;sleep 1;echo ‘###################’;done

Linux__程式概念詳解

可以從圖檔上看出三秒之後,子程序變成僵死狀态。

那父程序如果提前退出,子程序後退出會怎樣呢?這時候子程序就稱為孤兒程序了,應該由1号(作業系統)init程序領養,之後也由init程序回收。

int main()
{
    pid_t id = fork();
    int count = 0;
    if(id == -1){
        cerr << "fork error " << endl;
    }
    if(id == 0){//chlid
    while(1){
        cout << "I am chlid ..." << endl;
        sleep(1);
    }
    else
	{
		 while(1){//father
		 cout << "I am father " << endl;
		 sleep(1);
		 if(count++ >= 3)
             exit(1);   //退出程序
		 }
	}
	return 0;
}
           

跑腳本:while :; do ps axj | grep ‘myprocess’| grep -v grep ;sleep 1;echo ‘###################’;done

注:要看到父程序,需要将aux變成axj
           
Linux__程式概念詳解

可以看到當父程序退出之後,子程序被1号程序領養。

程序優先級

程序的優先權:CPU資源配置設定的先後順序。一般來說,數字越小優先級越高。

可以使用ps -l 指令檢視優先級

Linux__程式概念詳解

nice值為Linux下優先級的修正資料,nice其取值範圍是-20至19。

PRI = (舊的)PRI + nice

可使用top指令進行修改(一般不建議修改)

進入top之後按“r” —> 輸入程序ID —>輸入nice值

總結來說,如何管理程序就是先描述再組織,先把程序描述起來(就是這些表征資訊,都放在task_struct裡面),然後進行組織。

繼續閱讀