《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 通信與網(wǎng)絡(luò) > 設(shè)計(jì)應(yīng)用 > 基于linux平臺的進(jìn)程通信技術(shù)簡介
基于linux平臺的進(jìn)程通信技術(shù)簡介
華清遠(yuǎn)見
王姍姍
摘要: 基于linux平臺的進(jìn)程通信技術(shù)簡介,linux下的進(jìn)程通信手段基本上是從Unix平臺上的進(jìn)程通信手段繼承而來的。而對Unix發(fā)展做出重大貢獻(xiàn)的兩大主力AT&T的貝爾實(shí)驗(yàn)室及BSD(加州大學(xué)伯克利分校的伯克利軟件發(fā)布中心)在進(jìn)程間通信方面的側(cè)重點(diǎn)有所不同
Abstract:
Key words :

linux下的進(jìn)程通信手段基本上是從Unix平臺上的進(jìn)程通信手段繼承而來的,。而對Unix發(fā)展做出重大貢獻(xiàn)的兩大主力AT&T的貝爾實(shí)驗(yàn)室及BSD(加州大學(xué)伯克利分校的伯克利軟件發(fā)布中心)在進(jìn)程間通信方面的側(cè)重點(diǎn)有所不同。前者對Unix早期的進(jìn)程間通信手段進(jìn)行了系統(tǒng)的改進(jìn)和擴(kuò)充,,形成了“system V IPC”,通信進(jìn)程局限在單個(gè)計(jì)算機(jī)內(nèi),;后者則跳過了該限制,,形成了基于套接口(socket)的進(jìn)程間通信機(jī)制。Linux則把兩者繼承了下來,,如圖示:

 

其中,,最初Unix IPC包括:管道、FIFO,、信號,;System V IPC包括:System V消息隊(duì)列、System V信號燈,、System V共享內(nèi)存區(qū),;Posix IPC包括:

Posix消息隊(duì)列,、Posix信號燈、Posix共享內(nèi)存區(qū),。有兩點(diǎn)需要簡單說明一下:

1)由于Unix版本的多樣性,,電子電氣工程協(xié)會(IEEE)開發(fā)了一個(gè)獨(dú)立的Unix標(biāo)準(zhǔn),,這個(gè)新的ANSI Unix標(biāo)準(zhǔn)被稱為計(jì)算肪車目梢浦殘圓僮饗低辰緱媯≒SOIX)?,F(xiàn)有大部分Unix和流行版本都是遵循POSIX標(biāo)準(zhǔn)的,而Linux從一開始就遵循POSIX標(biāo)準(zhǔn),;

2)BSD并不是沒有涉足單機(jī)內(nèi)的進(jìn)程間通信(socket本身就可以用于單機(jī)內(nèi)的進(jìn)程間通信),。事實(shí)上,很多Unix版本的單機(jī)IPC留有BSD的痕跡,,如4.4BSD支持的匿名內(nèi)存映射,、4.3+BSD對可靠信號語義的實(shí)現(xiàn)等等。

linux下進(jìn)程間通信的幾種主要手段簡介:


1,、管道

管道是進(jìn)程間通信中最古老的方式,,它包括無名管道和有名管道兩種,前者可用于具有親緣關(guān)系進(jìn)程間的通信,,即可用于父進(jìn)程和子進(jìn)程間的通信,,后者額克服了管道沒有名字的限制,因此,,除具有前者所具有的功能外,,它還允許無親緣關(guān)系進(jìn)程間的通信,即可用于運(yùn)行于同一臺機(jī)器上的任意兩個(gè)進(jìn)程間的通信,。

無名管道由pipe()函數(shù)創(chuàng)建:

#include

int pipe(int filedis[2]),;

參數(shù)filedis返回兩個(gè)文件描述符:filedes[0]為讀而打開,filedes[1]為寫而打開,。filedes[1]的輸出是filedes[0]的輸入,。

在Linux系統(tǒng)下,有名管道可由兩種方式創(chuàng)建:命令行方式mknod系統(tǒng)調(diào)用和函數(shù)mkfifo,。下面的兩種途徑都在當(dāng)前目錄下生成了一個(gè)名為myfifo的有名管道:

方式一:mkfifo("myfifo","rw");

方式二:mknod myfifo p

生成了有名管道后,,就可以使用一般的文件I/O函數(shù)如open、close,、read,、write等來對它進(jìn)行操作。


2,、消息隊(duì)列

消息隊(duì)列是消息的鏈接表,,包括Posix消息隊(duì)列system

V消息隊(duì)列。消息隊(duì)列用于運(yùn)行于同一臺機(jī)器上的進(jìn)程間通信,,它和管道很相似,,有足夠權(quán)限的進(jìn)程可以向隊(duì)列中添加消息,,被賦予讀權(quán)限的進(jìn)程則可以讀走隊(duì)列中的消息。消息隊(duì)列克服了信號承載信息量少,,管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點(diǎn),。

我們可以用流管道或者套接口的方式來取代它。


3,、共享內(nèi)存

共享內(nèi)存是運(yùn)行在同一臺機(jī)器上的進(jìn)程間通信最快的方式,,因?yàn)閿?shù)據(jù)不需要在不同的進(jìn)程間復(fù)制。通常由一個(gè)進(jìn)程創(chuàng)建一塊共享內(nèi)存區(qū),,其余進(jìn)程對這塊內(nèi)存區(qū)進(jìn)行讀寫,。共享內(nèi)存往往與其它通信機(jī)制,如信號量結(jié)合使用,,來達(dá)到進(jìn)程間的同步及互斥,。

首先要用的函數(shù)是shmget,它獲得一個(gè)共享存儲標(biāo)識符,。

#include

#include

#include

int shmget(key_t key, int size, int flag);

這個(gè)函數(shù)有點(diǎn)類似大家熟悉的malloc函數(shù),,系統(tǒng)按照請求分配size大小的內(nèi)存用作共享內(nèi)存。Linux系統(tǒng)內(nèi)核中每個(gè)IPC結(jié)構(gòu)都有的一個(gè)非負(fù)整數(shù)的標(biāo)識符,,這樣對一個(gè)消息隊(duì)列發(fā)送消息時(shí)只要引用標(biāo)識符就可以了,。這個(gè)標(biāo)識符是內(nèi)核由IPC結(jié)構(gòu)的關(guān)鍵字得到的,這個(gè)關(guān)鍵字,,就是上面第一個(gè)函數(shù)的key,。數(shù)據(jù)類型key_t是在頭文件sys/types.h中定義的,它是一個(gè)長整形的數(shù)據(jù),。在我們后面的章節(jié)中,,還會碰到這個(gè)關(guān)鍵字。

當(dāng)共享內(nèi)存創(chuàng)建后,,其余進(jìn)程可以調(diào)用shmat()將其連接到自身的地址空間中,。

void *shmat(int shmid, void *addr, int flag);

shmid為shmget函數(shù)返回的共享存儲標(biāo)識符,addr和flag參數(shù)決定了以什么方式來確定連接的地址,,函數(shù)的返回值即是該進(jìn)程數(shù)據(jù)段所連接的實(shí)際地址,,進(jìn)程可以對此進(jìn)程進(jìn)行讀寫操作。

使用共享存儲來實(shí)現(xiàn)進(jìn)程間通信的注意點(diǎn)是對數(shù)據(jù)存取的同步,,必須確保當(dāng)一個(gè)進(jìn)程去讀取數(shù)據(jù)時(shí),,它所想要的數(shù)據(jù)已經(jīng)寫好了。通常,,信號量被要來實(shí)現(xiàn)對共享存儲數(shù)據(jù)存取的同步,,另外,可以通過使用shmctl函數(shù)設(shè)置共享存儲內(nèi)存的某些標(biāo)志位如SHM_LOCK、SHM_UNLOCK等來實(shí)現(xiàn),。4,、信號量

 

信號量又稱為信號燈,它是用來協(xié)調(diào)不同進(jìn)程間的數(shù)據(jù)對象的,,而最主要的應(yīng)用是前一節(jié)的共享內(nèi)存方式的進(jìn)程間通信,。本質(zhì)上,信號量是一個(gè)計(jì)數(shù)器,,它用來記錄對某個(gè)資源(如共享內(nèi)存)的存取狀況,。一般說來,為了獲得共享資源,,進(jìn)程需要執(zhí)行下列操作:

(1) 測試控制該資源的信號量,。

(2) 若此信號量的值為正,,則允許進(jìn)行使用該資源,。進(jìn)程將進(jìn)號量減1。

(3) 若此信號量為0,,則該資源目前不可用,,進(jìn)程進(jìn)入睡眠狀態(tài),直至信號量值大于0,,進(jìn)程被喚醒,,轉(zhuǎn)入步驟(1)。

(4) 當(dāng)進(jìn)程不再使用一個(gè)信號量控制的資源時(shí),,信號量值加1,。如果此時(shí)有進(jìn)程正在睡眠等待此信號量,則喚醒此進(jìn)程,。

維護(hù)信號量狀態(tài)的是Linux內(nèi)核操作系統(tǒng)而不是用戶進(jìn)程,。我們可以從頭文件/usr/src/linux/include/linux/sem.h中看到內(nèi)核用來維護(hù)信號量狀態(tài)的各個(gè)結(jié)構(gòu)的定義。信號量是一個(gè)數(shù)據(jù)集合,,用戶可以單獨(dú)使用這一集合的每個(gè)元素,。要調(diào)用的第一個(gè)函數(shù)是semget,用以獲得一個(gè)信號量ID,。

#include

#include

#include

int semget(key_t key, int nsems, int flag);

key是前面講過的IPC結(jié)構(gòu)的關(guān)鍵字,,它將來決定是創(chuàng)建新的信號量集合,還是引用一個(gè)現(xiàn)有的信號量集合,。nsems是該集合中的信號量數(shù),。如果是創(chuàng)建新集合(一般在服務(wù)器中),則必須指定nsems,;如果是引用一個(gè)現(xiàn)有的信號量集合(一般在客戶機(jī)中)則將nsems指定為0,。

semctl函數(shù)用來對信號量進(jìn)行操作。

int semctl(int semid, int semnum, int cmd, union semun arg);

不同的操作是通過cmd參數(shù)來實(shí)現(xiàn)的,在頭文件sem.h中定義了7種不同的操作,,實(shí)際編程時(shí)可以參照使用,。

semop函數(shù)自動執(zhí)行信號量集合上的操作數(shù)組。

int semop(int semid, struct sembuf semoparray[], size_t nops);

semoparray是一個(gè)指針,,它指向一個(gè)信號量操作數(shù)組,。nops規(guī)定該數(shù)組中操作的數(shù)量。

下面,,我們看一個(gè)具體的例子,,它創(chuàng)建一個(gè)特定的IPC結(jié)構(gòu)的關(guān)鍵字和一個(gè)信號量,建立此信號量的索引,,修改索引指向的信號量的值,,最后我們清除信號量。


5,、套接口

套接口(socket)編程是實(shí)現(xiàn)Linux系統(tǒng)和其他大多數(shù)操作系統(tǒng)中進(jìn)程間通信的主要方式之一,。我們熟知的WWW服務(wù)、FTP服務(wù),、TELNET服務(wù)等都是基于套接口編程來實(shí)現(xiàn)的,。除了在異地的計(jì)算機(jī)進(jìn)程間以外,套接口同樣適用于本地同一臺計(jì)算機(jī)內(nèi)部的進(jìn)程間通信,。

此內(nèi)容為AET網(wǎng)站原創(chuàng),,未經(jīng)授權(quán)禁止轉(zhuǎn)載。