進程和task_struct

進程

什麼是進程?
進程就是正在計算機上執行的實例。我們知道可執行文件都是存儲在磁盤中,當計算機執行可執行文件時,才把可執行文件從磁盤中讀取到內存上.然後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死亡狀態:這個狀態只是一個返回狀態,不會在任務列表中看到
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章