一:多道程序設計
1-多道程設計的目的
for:提高吞吐量(作業道數/處理時間),我們可以從提高資源的利用率出發
2-單道程序設計缺點:
設備的利用率低,內存的利用率低,處理機的利用率低
比如CPU去訪問內存,CPU空轉.內存等待CPU訪問也是沒有任何操作的.要是有多個東西要去訪問不沖突的設備,單道就只有一個一個的等(明明可以直接同時訪問的)
通過多道程序處理
中間的CPU等待訪問設備A的時候,可以處理程序B,同時允許多個不沖突的設備同時訪問
3-多道程序設計的道數的選擇:
最好與系統資源數量相當.因為:如果過少,系統資源利用率低,如果過多,系統調度等等的開銷過大
4-隨著多道程序設計的思想到來,同時也帶來了許多問題:
1:如果程序個數多于處理機數量,應該如何分配
2:存儲資源的管理應該如何處理,比如:存儲器地址的獨立性or共享性?內存外存交換的分配和去配?相對地址和絕對地址的地址轉換?
3:設備資源如果分配,比如:分配機制,IO控制等等
二:進程的引入
在多道程序系統中,一個程序是:推進,暫停,推進,暫停的
暫停:需要我們保存現場(PSW+PC,REG)然后跳轉到目標位置
推進:恢復現場(REG,PSW+PC)然后跳轉到目前的地址
1:進程的概念:
可參與并發執行的程序,進程是具有一定獨立功能的程序關于一個數據集合的一次運行活動
(強調了并發和運行):注意哦,不是并行(微觀也是同時,要求多CPU),是并發(宏觀同時,微觀交替)
2:進程狀態和狀態的轉換
運行態:占用CPU中
就緒態:可以運行,等待CPU
等待態:等待某一個時間的發生
就緒->運行:獲得CPU
運行->就緒:被剝奪CPU
運行->等待:申請資源,但是還沒有送到
等待->就緒:得到資源
當然用戶感受不到上面的轉換過程
3:進程控制塊
是程序的靜態描述
有著:進程的
描述信息:
-:進程標識:pid
-:所屬用戶uid
進程的控制信息:
CPU,磁盤,網絡流的使用情況
當前的進程狀態
進程占有的資源信息:
在使用那些文件
在使用那些內存區域
在使用那些IO設備
處理機相關信息:PSW ,PC reg的值
4:進程的組成和上下文
組成:PCB+程序(代碼+數據+堆棧)
進程上下文:
進程的物理實體和支持進程運行的物理條件是指進程上下文:
包括:PCB+程序,
環境系統:地址空間,系統棧,打開文件表,地址映射寄存器,通用寄存器,PSW+PC
上下文切換:
由一個進程的上下文切換到另外一個進程的上下文
系統開銷:
運行操作系統完成系統管理工作所花費的時間和空間
5.進程的組織
鏈接形式
進程控制塊(PCB)以隊列形式組織,隊列類型不限于單向或雙向,也不一定遵循FIFO原則。
就緒隊列:系統可包含一個或多個就緒隊列
等待隊列:每個等待事件對應一個獨立的等待隊列
運行指示字:每個處理機配備一個運行指示字
索引方式
執行指針:指向當前正在執行的進程塊
就緒表指針:指向存儲就緒態PCB的就緒索引表
阻塞表指針:指向存儲阻塞態(等待)PCB的阻塞索引表
6:進程的類型與特征
分為系統進程,用戶進程
系統進程:運行操作系統程序,完成系統管理功能.
系統啟動后一直存在直到系統的關閉,執行一個無限的循環
管態,執行所有指令,優先級高于用戶進程
用戶進程:為用戶服務,不一定用戶自己寫的
特征:
--:并發性:可以和其他進程一起推進
--:動態性:動態的產生,消亡,等待等等
--:獨立性:單獨的調度1單元
--:交往性:可以和其他進程交互
--異步性:可以格子獨立,不可預知速度的推進
--:結構性:每個進程只有一個PCB
7:進程間相互聯系和相互作用
聯系:
相關進程:同一家族的進程,可以共享文件,需要相互同學,協調推進,(父進程可以監視子進程,子進程完成父進程提供的任務)
無關進程:沒有邏輯關系,同時執行,但是有資源的競爭,互斥,死鎖,餓死的問題
作用:
直接相互作用:發生在相關進程之間,有意識,無中間媒介
間接相互作用:發生在任何的進程之間,有媒介
8:進程的創建和撤銷
創建的時候,需要分配內存+加載程序_入就緒隊列
撤銷的時候:需要去配資源,撤銷PCB,通知父進程(有可能是正常的終止,指發生了地址越界偶然非法指令or 被kill)
(除了初始進程,其他的進程都是被父進程創建并形成家族的)
如果考慮創建和撤銷這兩個狀態,正常的進程的狀態轉移圖:
9:進程與程序的聯系和差別:
差別
1-程序(代碼段,數據結構集)是靜態的,是長期存放在磁盤的可執行文件,是一系列指令集合
2-進程是動態的,是程序的一次執行過程,有生命期
3-一個進程只能執行一個程序,一個程序可以被多個進程執行
聯系:
進程包括一個程序,進程就是程序的幾個運行
10.UNIX進程
PROC結構:保存的信息無論當進程在內存還是外存都是需要的
USER結構:內存中才是需要的,也可以和進程的程序一起移動到外存
-創建子進程
PID=fork() ???????//子進程是父進程的復制品,返回值是父進程為子進程的編號,子進程為0
-加載并執行新的程序
execl(prog,arg0,arg1......,)
后面的argx為參數,執行prog
-:撤銷
exit(Status) ?//Status為終止態, 然后喚醒父進程
-Abort終止進程
被終止子進程的父進程執行該指令.
可能因為:子進程使用資源過多or子進程任務超時or父進程退出OS,那么子進程也被禁止(但是在UNIX,子進程會以init為新的父進程)
當然也可以是kill來終止
pid=wait(&Status) //返回的是終止的子進程的PID,參數是子進程的終止狀態
使用程序描述:
main()
????{
????????int pid1,pid2,pid3,pid4,pid5,pid6,pid7,pid8;
????????int ?end_p1=end_p2=end_p3=end_p4=end_p5=…=end_p8=0;
????????int pid, status;
????????if((pid1=fork())= =0) execl("P1",0);
????????wait(&status);
????????if((pid2=fork())= =0) execl("P2",0);
????????if((pid3=fork())= =0) execl("P3",0);
????????if((pid4=fork())= =0) execl("P4",0);
????????do{ ???????//等待P2結束
??????????????pid=wait(&status);
??????????????if(pid= =pid2) end_p2=1;
??????????????if(pid= =pid3) end_p3=1;
??????????????if(pid= =pid4) end_p4=1;
????????}while(end_p2= =0);
????????
????if((pid5=fork())= =0) execl("P5",0);
????if((pid6=fork())= =0) execl("P6",0);
????do{ ???????//等待P3和P6結束
????????????pid=wait(&status);
????????????if(pid= =pid3) end_p3=1;
????????????if(pid= =pid4) end_p4=1;
????????????if(pid= =pid5) end_p5=1;
????????????if(pid= =pid6) end_p6=1;
????}while(end_p3= =0||end_p6= =0);
????if((pid7=fork())= =0) execl("P7",0);
????do{ ???????//等待P4,P5,P7結束
????????????pid=wait(&status);
????????????if(pid= =pid4) end_p4=1;
????????????if(pid= =pid5) end_p5=1;
????????????if(pid= =pid7) end_p7=1;
????}while(end_p4= =0||end_p5= =0||end_p7= =0);
?????if((pid8=fork())= =0) execl("P8",0);
?????wait(&status);
?????exit(0);
}
11.vfork和fork
fork:復制地址空間(code,data,stack)和控制結構(proc,user)
特點:父進程和子進程都有獨立的數據拷貝
問題:不加載新的程序:不能數據共享,不能描述有解緩沖區
?????加載程序:復制可能沒有意義,浪費空間
vfork:只復制了控制結構(proc+user),不復制地址空間
特點:
父進程和子進程共享地址空間
子進程可以使用execve改變其的虛擬地址空間
三:線程和輕進程
1.線程的引入:
為什么需要引入線程尼?
進程的切換需要上下文切換,但是內容太多了(PCB+程序+系統環境:地址空間,棧空間,文件表),開銷太大了,而且一個進程可能也有很多個事情需要同時的去做,但是傳統的進程不能夠很好的去表達這些關系(沒有良好的耦合關系),通訊也十分麻煩
所以就引入了線程,允許一個進程有多個線程,線程的上下文切換只涉及了reg和用戶棧,而且線程之間的通訊也會更加的方便.
2.線程的概念:
概念:進程中的一個相對獨立的執行流.
進程vs線程:
進程是資源的分配單位.
線程是執行的單位
多線程開發的優點:
-上下文切換快(地址空間不變)
-系統的開發小
-相關線程間的通訊容易(共享數據空間)
3.線程的結構:
下面是進程的:
下面是線程的:
4.線程控制塊:
TCB:標志著線程存在的數據結構,其中包含了對線程管理所需要的全部信息
(包括了:線程標識,現場狀態,調度參數,現場(通用寄存器,PC,SP),鏈接指針)
存放在對應的級別的空間:
用戶線程:目態空間
核心線程:系統空間
5.線程的實現:
用戶級線程ULT:
特點:
-基于library函數創建,系統不可見
-線程的創建,撤銷,狀態轉換都發生在目態(TCB在用戶空間)
-TCB在用戶空間,一個進程一個系統棧
-進程的狀態復雜
優點:
-不依賴操作系統,調度靈活
-同一進程中多線程切換快(不切換地址空間,共享數據空間)
缺點:
-同一個進程的線程不是真正的并行
-一個線程受阻,進程的其他線程阻塞
核心級線程KLT:
特點:
-基于系統調用實現
-創建,撤銷和狀態的轉換由操作系統完成(TCB在系統空間)
-線程是CPU調度的基本單位,進程的狀態沒有意義
優點:
-同一個進程的多線程可以并行的執行
-一個現場進入核心等待,其他的進程可以執行(多CPU)
缺點:
-系統的開銷大,同一個進程的多線程切換慢
-調度由系統實現,調度算法不夠靈活
混合線程:
結構:
6.線程的應用:
-處理內在由多控制流,有合作,需要數據共享的背景
-多線程優于多進程(切換上下文數量級差100倍)
-提高處理機和設備的并行性
-多處理機環境適合多線程的運用
例子:
對于一個IDE,一個線程用于檢查代碼的語法邏輯,一個用于渲染代碼不同意義的字體顏色,一個實現定時時鐘的定時保存
再比如一個WEB server請求,直接pop up 一個線程讓其去處理就好了
7.java線程:
四個狀態:
New:新創建的線程
Runnable:可運行狀態
Blocked:封鎖狀態
Dead:終止狀態
JVM:
java虛擬機:處于java和操作系統之間,做到了java的良好的跨平臺性質
java線程與操作系統線程之間的對應關系由JVM確定
四:作業
1.作業的概念:
用戶要求計算機系統為其完成的計算任務集合
2.作業步:
作用處理過程中一個相對獨立的步驟,一般一個作業步可由一個進程完成,某些作業步之間可以實現并行.
3.作業控制塊:
表示作業存在的數據結構其中包含系統對作業管理所需要的全部信息:作業名稱,作業狀態,調度參數,資源需求,相關進程,作業長度,在輸入井和輸出井中的存放位置,記賬信息
作業的分類:
批處理作業和交互式作業
-作業控制語言(JCL):描述批處理作業控制意圖的語言
-作業說明書(JCL語句的序列):一般一個特殊符號起始
-作業控制程序:解釋并處理作業說明書的程序
-作業控制進程:執行作業控制程序的進程
批處理作業:
-1:作業由假脫機輸入程序輸入到輸入井
-2:經過OS的調度程序選中后進入內存
-3:同時由作業調度程序為其建立作業控制進程,執行作業控制程序
-4:作業控制進程解毒讀作說明書的語句,并且根據作業步的要求建立對應的進程
交互式作業:
賬戶管理:
/etc/passwd文件(用戶名,口令,用戶根目錄,同組用戶,余額)
操作:
創建:由用戶提供,or系統建立
撤銷:刪除用戶目錄機器對應的文件,在passwd中刪除對應的entry
注冊:
login:用戶名
password:***
使用...
注銷:
顯式注銷:logoff or 隱式注銷(無操作)
作業
總結:作業進入內存后變為進程進行執行,一個作業一般有多個進程,一個進程一般又會劃分為一個偶or多個線程進行執行(如果不支持的話就會單線程執行)