IPC 機制簡介
概述
在Unix早期發展中,做出重大貢獻的兩大主力Bell實驗室和伯克利大學(BSD)在IPC(InterProcess Communication)方面的側重點有所不同。前者對Unix早期的進程間通信手段進行了系統的改進和擴充,形成了“System V IPC”,通信進程局限在單個計算機內;后者則跳過了該限制,形成了基於套接口(socket)的進程間通信機制。大牛人W.Richard Stevens 著有的《UNIX Network Programming》經典大作,含兩卷:卷一就是socket網絡通信,卷二是單機的IPC。
POSIX是IEEE為要在各種UNIX操作系統上運行的軟件,而定義API的一系列互相關聯的標准的總稱,其正式稱呼為IEEE 1003,而國際標准名稱為ISO/IEC 9945。此標准源於一個大約開始於1985年的項目。POSIX這個名稱是由開源領袖RMS應IEEE的要求而提議的一個易於記憶的名稱。它基本上是Portable Operating System Interface(可移植操作系統界面)的縮寫,而X則表明其對Unix API的傳承。Linux基本上逐步實現了POSIX兼容,但並沒有參加正式的POSIX認證。
從上面可以看出,Sys V IPC和POSIX IPC可以認為是對同一個東西的不同實現而已。兩者有相同的IPC工具——信號量、共享內存、消息隊列,雖然Sys V和POSIX提供的接口有些差異,但基本概念是一致的。
需要注意的是,POSIX提供了消息隊列的通知機制(參考 mq_notify()函數),而Sys V不提供類似的功能。相對而言,Sys V IPC 的歷史更為悠久,並且先后在所有的平台上都得到實現,接口比較復雜。POSIX IPC 是在Sys V IPC 出現很長一段時間以后才被設計出來的,這使得它有機會吸收Sys V的優缺點,是以POSIX在設計上能夠超越它的前輩,並提供了更為簡潔、對程序員也更有愛的接口。鑒於Sys V IPC年齡太大,我以為POSIX IPC API才代表未來的趨勢。
進程間信息共享方式:
1、 左邊的兩個進程共享存留於文件系統中某個文件上的某些信息,為訪問這些信息,每個進程都得穿越內核(例如read、write、lseek等)。
2、 中間兩個進程共享駐留於內核中的某些信息,例如pipe、消息隊列、信號量,訪問共享信息的每次操作涉及對內核的一次系統調用。
3、 右邊的兩個進程有一個雙方都能訪問的共享內存區,每個進程可以不經過內核直接訪問它,但共享該內存區的進程需要某種形式的同步。
IPC對象的持續性:
1、 隨進程持續,IPC對象一直存在到打開該對象的最后一個進程關閉該對象為止,例如pipe和fifo;
2、 隨內核持續,IPC對象一直存在到內核重新自舉或顯式刪除該IPC對象為止,例如信號量、消息隊列、共享內存;
3、 隨文件系統持續,IPC對象一直存在到顯式刪除該對象為止;
IPC對象的標識符
當兩個或多個無親緣關系的進程使用某種類型的IPC對象來交換信息時,該IPC對象必須有一個名字,這樣其中一個進程可以創建該IPC對象,其余進程則可以指定同一個IPC對象。對於一種給定的IPC類型,其可能的名字的集合稱為它的name space。
IPC類型 |
持續性 |
name space |
IPC打開后的標識符 |
pipe fifo |
隨進程 |
(無名) 路徑名 |
描述符 |
TCP socket UPD socket Unix socket |
IP + port IP + port 路徑名 |
||
POSIX互斥鎖 POSIX條件變量 POSIX讀寫鎖 fcntl記錄鎖 |
(無名) (無名) (無名) 路徑名 |
pthread_mutex_t指針 pthread_cond_t指針 pthread_rwlock_t指針 描述符 |
|
POSIX消息隊列 POSIX有名信號量 POSIX基於內存信號量 POSIX共享內存 |
隨內核 |
POSIX IPC名字 POSIX IPC名字 (無名) POSIX IPC名字 |
mqd_t值 sem_t指針 sem_t指針 描述符 |
System V消息隊列 System V信號量 System V共享內存 |
key_t鍵 key_t鍵 key_t鍵 |
System V IPC標識符 |
POSIX IPC
|
消息隊列 |
信號量 |
共享內存 |
Include |
<mqueue.h |
<sys/sem.h> |
<sys/shm.h> |
創建或打開IPC |
mq_open mq_close mq_unlink |
sem_open sem_close sem_unlink |
shm_open shm_unlink |
sem_init sem_destroy |
|||
控制IPC |
mq_getattr mq_setattr |
|
ftruncate fstat |
IPC操作函數 |
mq_send mq_receive mq_notify |
sem_wait sem_trywait sem_post sem_getvalue |
mmap munmap |
SystemV IPC
|
消息隊列 |
信號量 |
共享內存 |
Include |
<sys/msg.h> |
<sys/sem.h> |
<sys/shm.h> |
創建或打開IPC |
msgget |
semget |
shmget |
控制IPC |
msgctl |
semctl |
shmctl |
IPC操作函數 |
msgsnd msgrcv |
semop |
shmat shmdt |
RPC
本地過程調用(local procedure call),就是被調用的過程(函數)與調用過程處於同一個進程中,這也是我們所熟悉的函數調用方式。
遠程過程調用(remote procedure call, RPC),被調用過程和調用過程處於不同的進程中。通常稱調用者為Client,被調用的過程為Server。
RPC又分兩種情況:
1、單台主機上的RPC(門調用),即調用者和被調用者在同一台主機上面;
2、主機間的PRC,需要借助網絡傳輸;