一、進程
進程的引入多個程序在執行時,需要共享系統資源,從而導致各程序在執行過程中出現相互制約的關係,程序的執行表現出間斷性的特徵。
這些特徵都是在程序的執行過程中發生的,是動態的過程,而傳統的程序本身是一組指令的集合,是一個靜態的概念,無法描述程序在內存中的執行情況,即我們無法從程序的字面上看出它何時執行,何時停頓,也無法看出它與其它執行程序的關係,因此,程序這個靜態概念已不能如實反映程序併發執行過程的特徵。爲了深刻描述程序動態執行過程的性質,人們引入“進程(Process)”概念。
進程是一個具有獨立功能的程序關於某個數據集合的一次運行活動。它可以申請和擁有系統資源,是一個動態的概念,是一個活動的實體。它不只是程序的代碼,還包括當前的活動,通過程序計數器的值和處理寄存器的內容來表示。
進程是操作系統中最基本、重要的概念。是多任務程序系統出現後,爲了刻畫系統內部出現的動態情況,描述系統內部各道程序的活動規律引進的一個概念,所有多道程序設計操作系統都建立在進程的基礎上。
進程的組成
- 進程ID,進程組ID,用戶ID,組ID
- 環境
- 工作目錄
- 程序指令
- 寄存器
- 堆棧(Stack)
- 堆(Heap)
- 文件描述符
- 信號操作
- 共享庫
- 進程間通信工具 : 消息隊列、管道、信號量、共享內存
動態性:進程的實質是程序的一次執行過程,進程是動態產生,動態消亡的。
併發性:任何進程都可以同其他進程一起併發執行
獨立性:進程是一個能獨立運行的基本單位,同時也是系統分配資源和調度的獨立單位;
異步性:由於進程間的相互制約,使進程具有執行的間斷性,即進程按各自獨立的、不可預知的速度向前推進
結構特徵:進程由程序、數據和進程控制塊三部分組成。
進程與程序
- 程序是指令的有序集合,其本身沒有任何運行的含義,是一個靜態的概念。而進程是程序在處理機上的一次執行過程,它是一個動態的概念。
- 程序可以作爲一種軟件資料長期存在,而進程是有一定生命期的。程序是永久的,進程是暫時的。
- 進程更能真實地描述併發,而程序不能;進程是由程序和數據兩部分組成的。
- 進程具有創建其他進程的功能,而程序沒有。
- 在傳統的操作系統中,程序並不能獨立運行,作爲資源分配和獨立運行的基本單元都是進程。
進程的基本狀態及狀態之間的關係
狀態:運行、阻塞、掛起阻塞、就緒、掛起就緒
狀態之間的轉換:
- 準備就緒的進程,被CPU調度執行,變成運行態;
- 運行中的進程,進行I/O請求或者不能得到所請求的資源,變成阻塞態;
- 運行中的進程,進程執行完畢(或時間片已到),變成就緒態;
- 將阻塞態的進程掛起,變成掛起阻塞態,當導致進程阻塞的I/O操作在用戶重啓進程前完成(稱之爲喚醒),掛起阻塞態變成掛起就緒態,當用戶在I/O操作結束之前重啓進程,掛起阻塞態變成阻塞態;
- 將就緒(或運行)中的進程掛起,變成掛起就緒態,當該進程恢復之後,掛起就緒態變成就緒態;
進程間的通信方式
- 管道(pipe)及有名管道(named pipe):管道可用於具有親緣關係的父子進程間的通信,有名管道除了具有管道所具有的功能外,它還允許無親緣關係進程間的通信。
- 信號(signal):信號是在軟件層次上對中斷機制的一種模擬,它是比較複雜的通信方式,用於通知進程有某事件發生,一個進程收到一個信號與處理器收到一箇中斷請求效果上可以說是一致的。
- 消息隊列(message queue):消息隊列是消息的鏈接表,它克服了上兩種通信方式中信號量有限的缺點,具有寫權限得進程可以按照一定得規則向消息隊列中添加新信息;對消息隊列有讀權限得進程則可以從消息隊列中讀取信息。
- 共享內存(shared memory):可以說這是最有用的進程間通信方式。它使得多個進程可以訪問同一塊內存空間,不同進程可以及時看到對方進程中對共享內存中數據得更新。這種方式需要依靠某種同步操作,如互斥鎖和信號量等。
- 信號量(semaphore):主要作爲進程之間及同一種進程的不同線程之間得同步和互斥手段。
- 套接字(socket):這是一種更爲一般得進程間通信機制,它可用於網絡中不同機器之間的進程間通信,應用非常廣泛。
二、線程
線程(thread)是進程上下文(context)中執行的代碼序列,是進程中的一個實體,是被系統獨立調度和分派的基本單位 ,又被稱爲輕量級進程(light weight process)。在支持多線程的系統中,進程成爲資源分配和保護的實體,而線程是被調度執行的基本單元。
線程只擁有一點在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。
一個線程可以創建和撤消另一個線程,同一進程中的多個線程之間可以併發執行。由於線程之間的相互制約,致使線程在運行中呈現出間斷性。
線程是程序中一個單一的順序控制流程。在單個程序中同時運行多個線程完成不同的工作,稱爲多線程。
進程內的線程
- 一個線程對共享的系統資源進行修改,在這個進程內的其它線程也可以見到這種修改。
- 對於同一個數據,可能有兩個值相同的指針指向這個數據。
- 進程內的多個線程可以對同一個內存單元進行讀和寫操作,所以必須要採取顯式同步機制。
- 在同一個進程的地址空間下,線程間的通信消耗更小。
- 程序在操作系統中作爲進程方式存在、獲取資源、運行。
- 在一個進程內,線程可以創建其它線程。每個線程有各自的棧(stack)。
- 一個進程內所有的線程共享代碼段和數據段。
線程的生命週期
- 線程的標識:通常用一個整數來標識一個線程
- 線程的創建:自動創建從main函數開始的主線程,調用函數庫接口創建一個新的線程(pthread_create)
- 線程的終止:執行完畢,或者調用了pthread_exit,主線程退出導致整個進程會終止
線程的狀態
- 就緒(ready):線程等待可用的處理器。
- 運行(running):線程正在被執行。
- 阻塞(blocked):線程正在等待某個事件的發生(比如I/O的完成,試圖加鎖一個被上鎖的互斥量)。
- 終止(terminated):線程從起始函數中返回或者調用pthread_exit。
多線程的優點
- 創建一個線程比創建一個進程的代價要小
- 線程的切換比進程間的切換代價小
- 充分利用多處理器
- 數據共享
- 數據共享使得線程之間的通信比進程間的通信更高效
- 快速響應特性
- 在系統繁忙的情況下,進程通過獨立的線程及時響應用戶的輸入
線程的同步與互斥
當有多個線程的時候,經常需要去同步這些線程以訪問同一個數據或資源。例如,假設有一個程序,其中一個線程用於把文件讀到內存,而另一個線程用於統計文件中的字符數。當然,在把整個文件調入內存之前,統計它的計數是沒有意義的。但是,由於每個操作都有自己的線程,操作系統會把兩個線程當作是互不相干的任務分別執行,這樣就可能在沒有把整個文件裝入內存時統計字數。爲解決此問題,你必須使兩個線程同步工作。
所謂同步,是指散步在不同進程之間的若干程序片斷,它們的運行必須嚴格按照規定的某種先後次序來運行,這種先後次序依賴於要完成的特定的任務。如果用對資源的訪問來定義的話,同步是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源。
所謂互斥,是指散佈在不同進程之間的若干程序片斷,當某個進程運行其中一個程序片段時,其它進程就不能運行它們之中的任一程序片段,只能等到該進程運行完這個程序片段後纔可以運行。如果用對資源的訪問來定義的話,互斥某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。
由於線程共享同一進程的內存空間,多個線程可能需要同時訪問同一個數據。如果沒有正確的保護措施,對共享數據的訪問會造成數據的不一致和錯誤。
常用的同步機制:
- 臨界區(critical section)
- 信號量(simphore)
- 互斥量(mutex)
- 管程(monitor)
信號量(simphore)
信號量被定義爲一個整數變量,用兩個原子的操作wait和signal來操作信號量
wait:當執行wait時,如果信號量的值大於0,wait操作把信號量的值減1並返回;如果當前信號量的值爲非正數則wait會等待。
signal : signal操作對信號量的值加1,並喚醒哪些等待的進程
互斥量(mutex)
在同一時刻只能有一個線程能夠對互斥量加鎖 ,線程用互斥量對共享變量counter的互斥訪問:
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock( &count_mutex ) ;
counter++ ;
pthread_mutex_unlock( &count_mutex );
三、進程與線程的區別與聯繫
- 子進程和父進程有不同的代碼和數據空間,而多個線程則共享數據空間,每個線程有自己的執行堆棧和程序計數器爲其執行上下文.
- 多線程主要是爲了節約CPU時間,發揮利用,根據具體情況而定. 線程的運行中需要使用計算機的內存資源和CPU
進程和線程的關係:
(1)一個線程只能屬於一個進程,而一個進程可以有多個線程,但至少有一個線程。
(2)資源分配給進程,同一進程的所有線程共享該進程的所有資源。
(3)處理機分給線程,即真正在處理機上運行的是線程。
(4)線程在執行過程中,需要協作同步。不同進程的線程間要利用消息通信的辦法實現同步。線程是指進程內的一個執行單元,也是進程內的可調度實體.
進程與線程的區別:
(1)調度:線程作爲調度和分配的基本單位,進程作爲擁有資源的基本單位
(2)併發性:不僅進程之間可以併發執行,同一個進程的多個線程之間也可併發執行
(3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但可以訪問隸屬於進程的資源.
(4)系統開銷:在創建或撤消進程時,由於系統都要爲之分配和回收資源,導致系統的開銷明顯大於創建或撤消線程時的開銷。