UnixC 程序間通訊 IPC

2021-06-22 11:32:00 字數 4191 閱讀 3760

一、程序間通訊(ipc):unix / linux 系統基於多程序,程序和程序之間資料的互動。

1.常見的ipc:1)檔案    2)訊號    3)管道(fifo)    4)共享記憶體    5)訊息佇列    6)訊號量集    7)網路程式設計(socket)

2.共享記憶體、訊息佇列和訊號量集遵循相同的規範,統稱為 xsi ipc。

------------------------------------------

二、管道:一種僅做為互動媒介的ipc的特殊的檔案,不儲存任何的資料,檔名字尾.p,只有在有讀且有寫操作時才能暢通,否則阻塞。

1.管道有兩種用法:有名管道和無名管道。

1)有名管道:可用於所有程序之間的互動。無名管道:只能用於fork()建立的父子程序之間的互動。

2)有名管道:程式設計師建立管道檔案進行ipc。無名管道:系統建立和維護管道檔案進行ipc。

2.使用有名管道的步驟:

a.建立管道檔案:mkfifo命令|||mkfifo("...")函式 【touch 命令和 open()函式都無法建立管道檔案】。

b.像讀寫普通檔案一樣操作管道檔案。

c.可以刪除管道檔案。

注意:open 乙個管道檔案,許可權不要用 o_rdwr。

------------------------------------------

三、xsi ipc 的通用規範:每個 ipc 都由乙個內部的id做唯一的標識。內部id的獲取,需要借助與之對應外部key(型別 key_t)。

1. key 獲取的三種方式:

a 使用巨集 ipc_private 做 key,但外部無法獲取,基本不用。

b 使用ftok()獲取乙個 key。

c 在標頭檔案中為每個ipc統一分配唯一的 key。

2.通過key 獲取內部 id:msgget(2)、semget(2)、shmget(2)  

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

3.每種ipc 結構都提供了乙個 ***ctl()函式(查詢、修改和刪除)。

4.所有ipc 結構都是核心管理,不使用時需要手工刪除。

5.ipc 結構的相關命令:

ipcs  - 查詢當前的 ipc 結構

ipcrm - 刪除當前的 ipc 結構 (用 id 刪除)

選項:-a 所有 ipc 結構

-m 共享記憶體  shared memory segments

-q 訊息佇列  semaphore arrays(更常用)

-s 訊號量集  message queues

------------------------------------------

四、共享記憶體:以一塊共享的物理記憶體做媒介。共享記憶體雖然速度最快(效率最高的ipc),但當多個程序同時寫資料時,資料會互相覆蓋,導致混亂。

1.共享的實現(通常情況下,兩個程序無法直接對映相同的記憶體。):

a)核心先拿出一塊物理記憶體,核心 負責管理。

b)允許所有程序對這塊記憶體進行對映。則兩個不同的程序,就可以對映到相同的物理記憶體上,從而實現資訊的互動。

2.程式設計步驟:

a)獲取 key。

b)使用 shmget()函式用key建立 / 獲取內部的 id。

c)使用 shmat()掛接共享記憶體(對映)- shm_nattch;  /* no. of current attaches */可以像正常操作一樣使用共享記憶體。

d)使用 shmdt()脫接共享記憶體(解除對映)。

e)如果確定已經不再使用,可以使用shmctl()刪除共享記憶體。

3.相關函式:

1)獲取key:key_t ftok(const char *pathname, int proj_id);

/*ftok()函式使用給定的檔名(必須存在,可訪問的檔案)和proj_id的低8位(必須非零)來生成key_t型別system v ipc的key,適用於msgget(2), semget(2)或者shmget(2)。

*/

2)獲取(建立)內部id,並設定共享記憶體大小:int/*

id*/ shmget(key_t key, size_t size/*

共享記憶體的大小

*/, int shm***/*

flag獲取時:0;新建時:ipc_creat|0666(許可權)

*/);

3)掛載記憶體:void *shmat(int shmid, const void *shmaddr, int shm***);(和mmap相似)如:void *shmat(int shmid, 0, 0);/*if  shmaddr  is null, the system chooses a suitable (unused) address at which to attach the segment. */ /*return:on success shmat() returns the address of the  attached  shared  memory segment; on error (void *) -1 is returned。*/

4)脫接記憶體:int shmdt(const void *shmaddr);//shmaddr 是shmat()的返回值,首位址(虛擬)。

5)查詢、修改和刪除共享記憶體:int shmctl(int shmid, int cmd, struct shmid_ds *buf /*

結構體指標

*/ );

cmd 引數:1)ipc_stat - 查詢  2)ipc_set  - 修改  3)ipc_rmid - 按id 刪除ipc 結構

查詢時:會把共享記憶體的資訊放入第三個引數。

修改時:只有使用者id、組id和許可權可以修改,大小不可修改。

刪除時:第三個引數給 0 即可。刪除共享記憶體時,掛接數必須為 0 ,才能真正刪除,否則刪除只是做乙個標記,等掛接數為 0 時,才能真正刪除。

------------------------------------------

五、訊息佇列(fifo):存放訊息的佇列。

1.訊息佇列實現:資料先封入訊息中,然後再把訊息存入佇列。一般情況下,佇列有滿有空。可以解決多個程序同時寫資料的問題。

2.程式設計步驟:

a)得到外部的 key。

b)使用msgget()函式用key 建立 / 獲取乙個訊息佇列id。

c)把資料 / 訊息 存入佇列 或 從佇列中取出。//函式msgsnd()存入 / msgrcv()取出/* ipc_nowait 無等待,直接返回 */

d)如果不再使用訊息佇列,可以msgctl()刪除。

3.相關函式:

int msgsnd(int msqid/*

訊息佇列的id

*/, const void *msgp, size_t msgsz, int msg***);

a)msgp:訊息的首位址,其中訊息分為有型別訊息(更規範)和無型別訊息。

b)有型別訊息結構:

struct msg

c)size:是資料區域的大小,不包括 mtype的大小(有些時候也包括,規範情況下,不包括)。

d)flag:選項,可以是 0 代表阻塞(佇列滿了),也可以是ipc_nowait 代表非阻塞(佇列滿了直接返回錯誤)。

e)成功返回 0,失敗返回 -1。

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msg***);

a)msgtyp 可以讓接收者有選擇的接收訊息,值可能是:

0 - 接收任意型別的訊息(第乙個,先入先出)。

>0 - 接收型別為 mtype 的特定訊息。

<0 - 接收型別 小於等於 mtype 絕對值的訊息,從小到大接收。

b)成功返回接收到的資料大小,失敗返回 -1。

程序間通訊IPC

這兩天學習了 unix 的程序間通訊 ipc,這裡面有幾個很重要的基本概念,特別是訊息佇列和我的畢設很有關係,因此多說幾句。以前學習的程序間通訊方式,一般都是經由 fork 或exec 開啟檔案,或經過檔案系統。而 ipc是程序間通訊方式的統稱。下面一一道來。一 管道 管道是最老的 ipc形式。管道...

程序間通訊 IPC

part2 index1.html part2 index2.html linux至少支援如下ipc機制 同時支援posix和system v方式 streams ipc機制,linux本身不支援,有乙個單獨的安裝包 可以跨pc的程序通訊 互斥鎖或條件變數 動態初始化 不能使靜態分配 在共享記憶體中...

程序間通訊IPC

乙個大型的應用系統,往往需要眾多程序協作,程序間通訊的重要性顯而易見。首先,程序間通訊至少可以通過傳送開啟檔案來實現,不同的程序通過乙個或多個檔案來傳遞資訊,事實上,在很多應用系統裡,都使用了這種方法。但一般說來,程序間通訊 ipc interprocess communication 不包括這種似...