程序間通訊2

2021-08-13 04:05:53 字數 3573 閱讀 3339

什麼是訊號量

為了防止出現因多個程式同時訪問乙個共享資源而引發的一系列問題,我們需要一種方法,它可以通過生成並使用令牌來授權,在任一時刻只能有乙個執行程序訪問**的臨界區域。臨界區域是指執行資料更新的**需要獨佔式地執行。而訊號量就可以提供這樣的一種訪問機制,讓乙個臨界區同一時間只有乙個程序在訪問它,也就是說訊號量是用來調協程序對共享資源的訪問的。

訊號量是乙個特殊的變數,程式對其訪問都是原子操作,且只允許對它進行等待(即p(訊號變數))和傳送(即v(訊號變數))資訊操作。最簡單的訊號量是只能取0和1的變數,這也是訊號量最常見的一種形式,叫做二進位制訊號量。而可以取多個正整數的訊號量被稱為通用訊號量。這裡主要討論二進位制訊號量。

工作原理

由於訊號量只能進行兩種操作等待和傳送訊號,即p(sv)和v(sv),他們的行為是這樣的:

p(sv):如果sv的值大於零,就給它減1;如果它的值為零,就掛起該程序的執行

v(sv):如果有其他程序因等待sv而被掛起,就讓它恢復執行,如果沒有程序因等待sv而掛起,就給它加1.

舉個例子,就是兩個程序共享訊號量sv,一旦其中乙個程序執行了p(sv)操作,它將得到訊號量,並可以進入臨界區,使sv減1。而第二個程序將被阻止進入臨界區,因為當它試圖執行p(sv)時,sv為0,它會被掛起以等待第乙個程序離開臨界區域並執行v(sv)釋放訊號量,這時第二個程序就可以恢復執行。

建立

int

semget(key_t key, int num_sems, int sem_flags);

第乙個引數key是整數值(唯一非零),不相關的程序可以通過它訪問乙個訊號量,它代表程式可能要使用的某個資源,程式對所有訊號量的訪問都是間接的,程式先通過呼叫semget函式並提供乙個鍵,再由系統生成乙個相應的訊號識別符號(semget函式的返回值),只有semget函式才直接使用訊號量鍵,所有其他的訊號量函式使用由semget函式返回的訊號量識別符號。如果多個程式使用相同的key值,key將負責協調工作。

第二個引數num_sems指定需要的訊號量數目,它的值幾乎總是1。

第三個引數sem_flags是一組標誌,當想要當訊號量不存在時建立乙個新的訊號量,可以和值ipc_creat做按位或操作。設定了ipc_creat標誌後,即使給出的鍵是乙個已有訊號量的鍵,也不會產生錯誤。而ipc_creat | ipc_excl則可以建立乙個新的,唯一的訊號量,如果訊號量已存在,返回乙個錯誤。

semget函式成功返回乙個相應訊號識別符號(非零),失敗返回-1.

操作它的作用是改變訊號量的值:

int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);

第乙個引數 sem_id是由semget返回的訊號量識別符號,

第二個引數 sembuf結構的定義如下:

struct sembuf;

第三個引數 nsops:訊號操作結構的數量,恆大於或等於1

控制該函式用來直接控制訊號量資訊:

int semctl(int sem_id, int sem_num, int command, …);

如果有第四個引數,它通常是乙個union semum結構,定義如下:

union semun;

第乙個引數是訊號量集ipc識別符號。

第二個引數是操作訊號在訊號集中的編號,第乙個訊號的編號是0

第三個引數 command通常是下面兩個值中的其中乙個

setval:用來把訊號量初始化為乙個已知的值。p 這個值通過union semun中的val成員設定,其作用是在訊號量第一次使用前對它進行設定。

ipc_rmid:用於刪除乙個已經無需繼續使用的訊號量識別符號。

持續性系統v訊息佇列是隨核心持續,只有在核心重啟或者人工刪除時,該訊息佇列才會被刪除

鍵值訊息佇列的核心持續性要求每個訊息佇列都在系統範圍內對應唯一的鍵值,所以,要獲得乙個訊息佇列的描述符,必須提供該訊息佇列的鍵值。

#include 

#include

key_t ftok(char *pathname, char proj);

功能:返回檔名對應的鍵值。

pathname:檔名

proj:專案名(不為0即可)

開啟/建立

#include 

#include

#include

int msgget(key_t key, int msg***)

key: 鍵值,由ftok獲得

msg***:標誌位

返回值:與鍵值key相對應的訊息佇列的描述符。

msg***取值:

ipc_creat

建立新的訊息佇列

ipc_excl

與ipc_creat一同使用,表示如果要建立的訊息佇列已經存在,則返回錯誤。

ipc_nowait

讀寫訊息佇列要求無法得到滿足時,不阻塞。

在以下兩種情況下,將建立乙個新的訊息佇列:

如果沒有與鍵值key相對應的訊息佇列,並且msg***中包含了ipc_creat標誌位。

key引數為ipc_private

傳送訊息

#include 

#include

#include

int msgsnd(int msqid, struct msgbuf * msgp, int msgsz, int msg***)

功能:向訊息佇列中傳送一條訊息

msqid:訊息佇列描述符

msgp:訊息佇列指標,指向存放訊息的結構

msgsz:訊息資料長度

msg***:傳送標誌,有意義的msg***標誌為ipc_nowait,指明在訊息佇列沒有足夠空間容納要傳送的訊息時,msgsnd是否等待

訊息格式:

struct msgbuf

接收訊息
#include 

#include

#include

int msgrcv(int msqid, struct msgbuf* msgp, int msgsz, long msgtp, int msg***)

功能:從msqid代表的訊息佇列中讀取乙個msgtyp型別的訊息,並把訊息儲存在msgp指向的msgbuf結構中。在成功的讀取了一條訊息以後,佇列中的這條訊息將被刪除。

佇列控制

int msgctl(int msgid, int command, struct msgid_ds *buf);

command是將要採取的動作,它可以取3個值,

ipc_stat:把msgid_ds結構中的資料設定為訊息佇列的當前關聯值,即用訊息佇列的當前關聯值覆蓋msgid_ds的值。

ipc_set:如果程序有足夠的許可權,就把訊息列隊的當前關聯值設定為msgid_ds結構中給出的值

ipc_rmid:刪除訊息佇列

buf是指向msgid_ds結構的指標,它指向訊息佇列模式和訪問許可權的結構。msgid_ds結構至少包括以下成員:

struct msgid_ds  

;

成功時返回0,失敗時返回-1.

程序間通訊方式(2)

q 訊息佇列實質及運用?a 訊息佇列就是乙個訊息的鍊錶,把訊息看作有特定格式和優先順序的記錄,該記錄包括訊息佇列鍵值,使用者 id,組 id,訊息佇列中訊息數目等,甚至可以包括對訊息佇列讀寫程序的 id。對於訊息有相應許可權的程序可以對訊息程序進行相應寫入和讀取操作 訊息佇列是隨著核心持續的。對於訊...

Linux 程序間通訊2

一 共享記憶體 1 共享記憶體是被多個程序共享的一部分物理記憶體.共享記憶體是程序間共享資料的一種最快的方法,乙個程序向共享記憶體區域寫入了資料,共享這個記憶體區域的所有程序就可以 立刻 看到其中的內容 2.共享記憶體實現分為兩個步驟 一 建立共享記憶體,使用shmget函式 二 對映共享記憶體,將...

程序間通訊(2) 管道

管道 本質 核心的快取 管道分類 管道是程序間通訊中最古老的方式,它是指用於連線乙個讀程序和乙個寫程序以實現他們之間通訊的乙個共享檔案。我們將乙個程序到另乙個程序的資料流,稱之為 管道 它包括匿名管道和命名管道兩種。匿名管道 include h 功能 建立乙個無名管道 原型 int pipe int...