進程
什麼是進程?
進程就是正在計算機上執行的實例。我們知道可執行文件都是存儲在磁盤中,當計算機執行可執行文件時,才把可執行文件從磁盤中讀取到內存上.然後cpu從內存上讀取指令來運行程序,那在內存上等待或者正在被cpu執行的程序就是進程。
操作系統是怎樣標識進程的?
在進程執行時,anytime,進程總是被以下元素表示:
- 標識符:用以和其他進程區分,比如說PID
- 狀態:表示程序當前狀態,比如說是就緒,睡眠,正在執行等
- 程序計數器:程序即將被執行的下一條指令的地址
- 內存指針:一些和程序代碼,進程相關數據,還有和其他進程共享的數據塊的指針
- 上下文數據:程序執行時處理器和寄存器中的數據,比如說程序離開後通過這個又可以回來
- I/O狀態信息:一些顯示的I/O請求,分配給進程的I/O設備和被進程使用的頭文件列表等
- 記賬信息:包括處理器的時間總和,使用的時鐘數總和,時間限制,記賬號等
這些東西都保存在PCB(程序控制塊)中,由專門的結構體來管理,在Linux中由task_struct結構體來管理,下面看一下0.11內核版本的task_struct結構體:
struct task_struct{
long state; //運行狀態-1-unrunnable,1-runnable,0-stopped
long counter; //運行時間計數(滴答數)
long priority; //運行優先數,開始運行時counter = priority,越大運行越長
long signal; //信號,每個比特代表一種信號
struct sigaction sigaction[32];//信號執行屬性結構
//對應信號要執行的操作和標誌信息
long blocked; //進程信號屏蔽碼(對應信號位圖)
/****/
int exit_code;//任務執行停止的退出碼,其父進程會取
unsigned long start_code;//代碼段地址
unsigned long end_code;//代碼段長度(字節數)
unsigned long end_data;//代碼長度+數據長度(字節數)
unsigned long brk;//總長度(字節數)
unsigned long strat_stack;//堆棧段地址
long pid;//進程號
long father;//父進程號
long pgrp;//組進程號
long session;//會話號
long leader;//會話首領
unsigned short uid;//用戶id
unsigned short euid;//有效用戶id
unsigned short suid;//保存的用戶id
unsigned short gid;//組id
unsigned short egid;//有效組id
unsigned short sgid;//保存的組id
long alarm;//報警定時值(滴答數)
long utime;//用戶態運行時間(滴答數)
long stime;//系統運行時間(滴答數)
long cutime;//子進程用戶態運行時間
long cstime;//子進程系統態運行時間
long start_time;//進程開始運行時刻
unsigned short usde_math;//標誌:是否使用了協處理器
/******/
int tty;//進程使用tty的子設備號,-1表示沒有使用
unsigned short umask;//文件創建屬性屏蔽位
struct m_inode* pwd;//當前工作目錄i結點結構
struct m_inode* root;//根目錄i結點結構
struct m_inode* executable;//執行文件i結點結構
unsigned short close_on_exec;//執行時文件關閉文件句柄位圖標誌
struct file* filp[NP_OPEN];//進程使用的文件表結構
/******/
struct desc_struct ldt[3];//本任務的局部描述符,
//0-空,1-代碼段cs,2-數據和堆棧段ds&ss
/*****/
struct tss_struct tss;//本進程任務狀態段信息結構
}
通過fork()創建進程
一個現有的進程可以通過frok函數創建一個新的進程,由fork創建的新進程被稱爲子進程,其函數由兩個返回值–子進程返回0,父進程返回子進程的PID,失敗返回-1。子進程可以通過getpid函數獲得父進程的PID。
執行fork後,子進程是父進程的副本,其獲得父進程的數據空間,堆和棧的副本,等於是以父進程爲模板,拷貝一份PCB,內存指針指向同一份代碼,數據父子進程各自擁有一份, 父進程和子進程的執行順序不確定, PC指針和父進程共用一份
子進程繼承了父進程的:
- 實際用戶ID,實際組ID,有效用戶ID,有效組ID
- 附加組ID
- 進程組ID
- 會話ID
- 控制終端
- 文件描述符
- 設置用戶ID標誌和設置zuID標誌
- 當前工作目錄
- 根目錄
- 文件模式創建屏蔽字
- 信號屏蔽和安排
- 針對任一打開文件描述符的在執行時關閉標誌(close-on-exec)
- 環境
- 連接的共享存儲段
- 存儲映射
子進程和父進程的區別:
- fork的返回值
- 進程ID不同
- 子進程的tms_utime,tms_stime,tms_ctime以及tms_ustime被設置爲0
- 父進程設置的文件鎖
- 子進程未處理的鬧鐘被清除
- 子進程未處理的信號集被置空
進程狀態
一個進程可以有不同的狀態
- R運行狀態:在運行中或者在運行隊列裏
- S睡眠狀態:程序在等待世間的完成
- D磁盤休眠狀態:在這個狀態的進程通常會等待IO的結束
- T停止狀態:可以通過發送SIGSTOP信號給進程來停止(T)進程,這個被停址的進程可以通過SIGCONT信號讓進程繼續運行
- X死亡狀態:這個狀態只是一個返回狀態,不會在任務列表中看到