程序
程序指正在執行的程式。從核心來說,它是擔當配置設定系統資源(CPU時間,記憶體)的實體。
那程序跟程式有什麼差別呢?從資料和代碼層面看,它們是一樣的,但是程序比程式多了一個東西,那就是描述程序的PCB結構體。
那這個PCB到底有什麼作用呢?
PCB
相信學過作業系統的同學都知道,作業系統作為軟體和硬體的管理者,那作業系統要管理那麼多的程序,而每個程序都有很多的資訊,為了友善管理這些程序資訊,它們被放在一個叫做程序控制塊的資料結構中,我們稱之為PCB。
在Linux中描述程序的結構體叫做task_struct。它是Linux核心的一種資料結構,會被裝載到記憶體裡。
task_ struct内容分類
辨別符(PID) :跟這個程序相關的唯一辨別符,用來差別其他程序
狀态 :如果程序正在執行,那麼程序處于執行狀态。
優先級 :相對于其他程序的優先級。
程式計數器 :程式中即将被執行的下一條指令的位址。
記憶體指針:包括程式代碼和程序相關資料的指針,還有和其他程序共享的記憶體塊的指針。
上下文資料:程序執行時處理器的寄存器中的資料。
I/O狀态資訊:包括顯示的I/O請求,配置設定給程序的I/O裝置(如錄音帶驅動器)和被程序使用的檔案清單。
審計資訊:可包括處理器時間總和,使用的時鐘數總和,時間限制,審計号等。
辨別符(PID)
在Linux下可以使用top指令(相當于windows系統下的任務管理器)可以檢視
也可以使用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;
}
可以看到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
可以從圖檔上看出三秒之後,子程序變成僵死狀态。
那父程序如果提前退出,子程序後退出會怎樣呢?這時候子程序就稱為孤兒程序了,應該由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
可以看到當父程序退出之後,子程序被1号程序領養。
程序優先級
程序的優先權:CPU資源配置設定的先後順序。一般來說,數字越小優先級越高。
可以使用ps -l 指令檢視優先級
nice值為Linux下優先級的修正資料,nice其取值範圍是-20至19。
PRI = (舊的)PRI + nice
可使用top指令進行修改(一般不建議修改)
進入top之後按“r” —> 輸入程序ID —>輸入nice值
總結來說,如何管理程序就是先描述再組織,先把程序描述起來(就是這些表征資訊,都放在task_struct裡面),然後進行組織。