進程

進程基本概念

進程包括程序代碼(又稱文本段或代碼段),當前活動(通過Program Counter和當前寄存器內的內容表示),進程堆棧段(包括臨時數據,比如函數參數、返回地址和局部變數)和數據段(包括全局變數),堆(用於運行時動態分配內存)。

程序:靜態的內容,可執行文件。

進程:活動的實體,有PC表示下一個要執行的命令和相關資源集合。

進程的狀態

進程狀態圖

PCB

PCB圖

進程狀態:上面說的new, ready, running, waiting, terminate

PC:表示進程要執行的下個指令的地址

CPU寄存器:包括累加器,索引寄存器,堆棧指針、通用寄存器和其它條件碼信息寄存器,用於保存一些中間狀態,以便之後能順利執行(比如執行了中斷之後)

CPU調度信息:進程優先順序,調度隊列指針和其它參數等

內存管理信息:基址寄存器和界限寄存器,頁表或段表

記賬(Accounting)信息:包括CPU時間、實際使用時間、時間界限、記賬數據、作業或進程數量等

I/O狀態信息:包括分配給進程的I/O設備列表,打開的文件列表等

進程間切換

進程間切換的表示圖

進程調度基本概念

進程進入系統的時候會被加入作業隊列中,作業隊列保存了系統中的所有進程。

已經被調入內存中等待執行的的進程會進入Ready queue。

隊列用鏈表表示,有頭尾指針,以及指向當前正在運行的進程的current指針。

等待I/O的設備會被放進設備隊列。

調度隊列中有一個指針表示當前正在執行的進程

Scheduler分為Long-term Scheduler和Short-term Scheduler。

對於批處理系統來說,long-term scheduler負責將提交了的作業從緩衝池中取出放進內存中(即放進Ready queue中),short-term scheduler(又叫做CPU scheduler)負責將進程從Ready queue中取出。

short-term scheduler因為需要頻繁執行調度,所以必須調度的速度要儘可能快。long-term scheduler需要選擇合適組合I/O-bound進程(大部分時間在做設備I/O)和CPU-bound進程(大部分時間在做計算)。不是所有的操作系統都有long-term scheduler。

time-sharing系統可能需要引入medium-term scheduler。medium-term scheduler的思想是能將進程從內存(and from active contention for the CPU)中移出,and thus reduce the degree of multi-programming。之後進程還能再被調入內存中繼續執行。這叫swapping。

通常,通過state save保存CPU當前狀態(不管是在kernel mode還是在user mode),之後通過state store重新執行。

上下文切換(context switch)的定義:Switching the CPU to another process requires performing a state save of the current process and a state restore of a different process. This task is known as a context switch.

上下文切換髮生時,內核將就舊進程的狀態保存在PCB中,然後裝入要執行的進程的上下文。

上下文切換屬於額外的時間開銷,速度因機器不同而不同。

進程創建

When a process creates a new process, two possibilities for execution exist:

1. The parent continues to execute concurrently with its children.

2. The parent waits until some or all of its children have terminated.

There are also two address-space possibilities for the new process:

1. The child process is a duplicate of the parent process (it has the same program and data as the parent).

2. The child process has a new program loaded into it.

UNIX系統中每個進程都用一個唯一的整數標識。父進程和子進程間可以通信。兩者都繼續執行fork()之後的指令。對於子進程來說,fork()的返回值為0;對於父進程來說,返回值為子進程的進程標識符pid。

通常系統在調用fork()之後還會繼續執行exec()來執行子進程,這樣子進程會取代父進程的內存空間。父進程能繼續創造更多的子進程,也可以通過wait()把自己從ready queue中移出,等待子進程終止。

進程終止

當進程完成執行最後的語句並使用系統調用exit()請求系統刪除自身的時候,進程終止。這個時候進程可以通過返回狀態值到父進程處(如果父進程執行了wait())。所有使用的資源(包括物理內存和虛擬內存,打開的文件,I/O緩衝)都會被系統釋放。

A parent may terminate the execution of one of its children for a variety of

reasons, such as these:

? The child has exceeded its usage of some of the resources that it has been allocated. (To determine whether this has occurred, the parent must have a mechanism to inspect the state of its children.)

? The task assigned to the child is no longer required.

? The parent is exiting, and the operating system does not allow a child to continue if its parent terminates.

進程通信

There are several reasons for providing an environment that allows process cooperation(進程協作):

? Information sharing. Since several users may be interested in the same piece of information (for instance, a shared file), we must provide an environment to allow concurrent access to such information.

? Computation speedup. If we want a particular task to run faster, we must break it into sub-tasks, each of which will be executing in parallel with the others. Notice that such a speedup can be achieved only if the computer has multiple processing cores.

? Modularity. We may want to construct the system in a modular fashion, dividing the system functions into separate processes or threads, as we discussed in Chapter 2.

? Convenience. Even an individual user may work on many tasks at the same time. For instance, a user may be editing, listening to music, and compiling in parallel.

進程需要IPC(進程間通信機制)來允許進程相互交換信息和數據。進程間通信有兩種基本模式:共享內存消息傳遞。在共享內存的模式中,兩者可以共同讀寫訪問一塊共享的內存區域來交換信息。在消息傳遞模式中,通過進程間交換信息來實現通信。

進程間通信模型

內存共享比消息傳遞快。消息傳遞系統通常需要系統調用來實現;而在共享內存系統,僅在簡歷共享內存區域的時候需要系統調用,在建立共享內存之後,所有的訪問都是常規的內存訪問。

共享內存系統

生產者-消費者問題:生產者進程產生信息以提供消費者進程消費。比如client-server中,client是生產者而server是消費者。

為了允許生產者進程的消費者進程能並發執行,必須有一個buffer來被生產者填充,冰杯消費者所使用。這個buffer是在生產者進程和消費者進程的共享內存區域內的,當消費者使用一項的時候,生產者進程能產生另外一項,且生產者和消費者必須同步,以免消費者消費一個未被生產出的項。

其中unbounded-buffer是對buffer的大小沒有限制,即消費者可能不得不等待新的項,但是生產者可以不停地生產新的項。bounded-buffer假設buffer大小固定,這樣的話如果buffer為空,那麼消費者必須等待;如果buffer為滿的,那麼生產者必須等待。


推薦閱讀:

找到Linux虛機Load高的"元兇"
如何利用秒級監控進行mongodb故障排查
夏周:阿里雲 Redis 容災體系介紹

TAG:操作系統 | 操作系統原理 | 多線程 | 內存管理 | 線程 |