Q1: 進程間的通信方式
1. 匿名管道
管道是通過調用 pipe 函數創建的,fd[0] 用於讀,fd[1] 用於寫
int pipe(int fd[2]);
存在形式:
無名管道:只存在於內存中的文件
使用限制:
- 只支持半雙工(單向交替傳輸)
- 只能在父子進程或兄弟進程中使用
2. 命名管道
解決了匿名管道的只能在父子進程中使用的限制。
存在形式:
命名管道:存在於實際的磁盤介質或者文件系統
#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode);
FIFO 常用於客戶-服務器應用程序中,FIFO 用作匯聚點,在客戶進程和服務器進程之間傳遞數據。
管道的實現機制:
管道是由內核管理的一個緩衝區,這個緩衝區被設計成爲環形的數據結構,以便管道可以被循環利用。當管道中沒有信息的話,從管道中讀取的進程會等待,直到另一端的進程放入信息。當管道被放滿信息的時候,嘗試放入信息的進程會等待,直到另一端的進程取出信息。
3. 消息隊列
消息隊列是消息的鏈表,具有特定的格式,存放在內存中並由消息隊列標識符標識。 進程控制塊(PCB)中有對應的字段會保存對應消息隊列的標識符.
存在形式:
消息隊列存放在內核中,只有在內核重啓(即,操作系統重啓)或者顯示地刪除一個消息隊列時,該消息隊列纔會被真正的刪除。
消息隊列的優點:
- 可以對消息隨機讀取,而不是像管道那樣只能FIFO
- 比起管道, 消息隊列能存儲的信息更多更豐富
4. 信號量
信號量可以理解成一個計數器,用於解決多個進程訪問共享資源時的同步問題。
5. 共享內存
使多個進程可以訪問同一塊內存空間,不同進程可以及時看到對方進程中對共享內存中數據的更新。 這種方式需要依靠某種同步操作,例如:互斥鎖和信號量等。
6. 套接字
此方法主要用於不在同一臺機器上的進程間的通信,例如客戶端的一個進程和服務端的一個進程進行通信。
Q2: 線程間的同步方式有哪些
1. 互斥量(mutex) (搶佔式同步)
就是上鎖,在java中主要就是 synchronized 和 各種Lock.
2. 信號量(Semphore) (非搶佔式同步)
允許多個線程訪問同一個資源,但需要控制同一時刻訪問此資源的最大線程數量
3. Java對管程的實現( wait / notify )
通過wait和notify來實現同步
Q3:死鎖產生的條件
1. 互斥
每一個資源只能分給一個進程.
2. 佔用和等待
已經得到了某個資源的進程可以再請求新的資源. 並且可以在持有一些資源的狀態下去等待暫時無法獲取的資源
3. 不可搶佔
已經分配給一個進程的資源,在這個進程沒有使用完或主動釋放之前,都不能被其他進程獲取.
4. 環路等待
Q4: 解決死鎖的策略:
1. 鴕鳥策略(解決策略就是不去解決)
因爲解決死鎖的代價會比較大,且死鎖發生的概率又比較小,並且死鎖也不會對用戶造成致命影響的話,那麼就忽略它好了…
2. 死鎖檢測與死鎖恢復
不試圖阻止死鎖,而是當檢測到死鎖發生的時候,採取一些措施進行一個恢復
檢測到死鎖後的恢復策略:
- 利用搶佔恢復
- 利用回滾恢復
- 通過殺死進程恢復
其實就是破壞死鎖的必要條件中的一個就行了…
3. 死鎖預防
在程序運行之前就預防發生死鎖,就是破壞死鎖產生的必要條件中的一個就行。
例如:
- 給資源統一編號,進程只能按編號順序來請求資源,破壞了環路等待;
- 分配資源時,一次性把所有資源都分配出去, 破壞了佔有並等待;
4. 死鎖避免
在程序運行時,避免發生死鎖。 使用銀行家算法,保證在資源分配後依然能讓系統處於安全狀態… 如果不安全的話就拒絕分配.