基于linux平臺的進(jìn)程通信技術(shù)簡(jiǎn)介
linux下的進(jìn)程通信手段基本上是從Unix平臺上的進(jìn)程通信手段繼承而來(lái)的。而對Unix發(fā)展做出重大貢獻的兩大主力ATamp;T的貝爾實(shí)驗室及BSD(加州大學(xué)伯克利分校的伯克利軟件發(fā)布中心)在進(jìn)程間通信方面的側重點(diǎn)有所不同。前者對Unix早期的進(jìn)程間通信手段進(jìn)行了系統的改進(jìn)和擴充,形成了“system V IPC”,通信進(jìn)程局限在單個(gè)計算機內;后者則跳過(guò)了該限制,形成了基于套接口(socket)的進(jìn)程間通信機制。Linux則把兩者繼承了下來(lái),如圖示:
本文引用地址:http://dyxdggzs.com/article/150010.htm其中,最初Unix IPC包括:管道、FIFO、信號;System V IPC包括:System V消息隊列、System V信號燈、System V共享內存區;Posix IPC包括:
Posix消息隊列、Posix信號燈、Posix共享內存區。有兩點(diǎn)需要簡(jiǎn)單說(shuō)明一下:
1)由于Unix版本的多樣性,電子電氣工程協(xié)會(huì )(IEEE)開(kāi)發(fā)了一個(gè)獨立的Unix標準,這個(gè)新的ANSI Unix標準被稱(chēng)為計算環(huán)境的可移植性操作系統界面(PSOIX)?,F有大部分Unix和流行版本都是遵循POSIX標準的,而Linux從一開(kāi)始就遵循POSIX標準;
2)BSD并不是沒(méi)有涉足單機內的進(jìn)程間通信(socket本身就可以用于單機內的進(jìn)程間通信)。事實(shí)上,很多Unix版本的單機IPC留有BSD的痕跡,如4.4BSD支持的匿名內存映射、4.3+BSD對可靠信號語(yǔ)義的實(shí)現等等。
linux下進(jìn)程間通信的幾種主要手段簡(jiǎn)介:
1、管道
管道是進(jìn)程間通信中最古老的方式,它包括無(wú)名管道和有名管道兩種,前者可用于具有親緣關(guān)系進(jìn)程間的通信,即可用于父進(jìn)程和子進(jìn)程間的通信,后者額克服了管道沒(méi)有名字的限制,因此,除具有前者所具有的功能外,它還允許無(wú)親緣關(guān)系進(jìn)程間的通信,即可用于運行于同一臺機器上的任意兩個(gè)進(jìn)程間的通信。
無(wú)名管道由pipe()函數創(chuàng )建:
#include unistd.h>
int pipe(int filedis[2]);
參數filedis返回兩個(gè)文件描述符:filedes[0]為讀而打開(kāi),filedes[1]為寫(xiě)而打開(kāi)。filedes[1]的輸出是filedes[0]的輸入。
在Linux系統下,有名管道可由兩種方式創(chuàng )建:命令行方式mknod系統調用和函數mkfifo。下面的兩種途徑都在當前目錄下生成了一個(gè)名為myfifo的有名管道:
方式一:mkfifo(myfifo,rw);
方式二:mknod myfifo p
生成了有名管道后,就可以使用一般的文件I/O函數如open、close、read、write等來(lái)對它進(jìn)行操作。
2、消息隊列
消息隊列是消息的鏈接表,包括Posix消息隊列system
V消息隊列。消息隊列用于運行于同一臺機器上的進(jìn)程間通信,它和管道很相似,有足夠權限的進(jìn)程可以向隊列中添加消息,被賦予讀權限的進(jìn)程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無(wú)格式字節流以及緩沖區大小受限等缺點(diǎn)。
我們可以用流管道或者套接口的方式來(lái)取代它。
3、共享內存
共享內存是運行在同一臺機器上的進(jìn)程間通信最快的方式,因為數據不需要在不同的進(jìn)程間復制。通常由一個(gè)進(jìn)程創(chuàng )建一塊共享內存區,其余進(jìn)程對這塊內存區進(jìn)行讀寫(xiě)。共享內存往往與其它通信機制,如信號量結合使用,來(lái)達到進(jìn)程間的同步及互斥。
首先要用的函數是shmget,它獲得一個(gè)共享存儲標識符。
#include sys/types.h>
#include sys/ipc.h>
#include sys/shm.h>
int shmget(key_t key, int size, int flag);
這個(gè)函數有點(diǎn)類(lèi)似大家熟悉的malloc函數,系統按照請求分配size大小的內存用作共享內存。Linux系統內核中每個(gè)IPC結構都有的一個(gè)非負整數的標識符,這樣對一個(gè)消息隊列發(fā)送消息時(shí)只要引用標識符就可以了。這個(gè)標識符是內核由IPC結構的關(guān)鍵字得到的,這個(gè)關(guān)鍵字,就是上面第一個(gè)函數的key。數據類(lèi)型key_t是在頭文件sys/types.h中定義的,它是一個(gè)長(cháng)整形的數據。在我們后面的章節中,還會(huì )碰到這個(gè)關(guān)鍵字。
當共享內存創(chuàng )建后,其余進(jìn)程可以調用shmat()將其連接到自身的地址空間中。
void *shmat(int shmid, void *addr, int flag);
shmid為shmget函數返回的共享存儲標識符,addr和flag參數決定了以什么方式來(lái)確定連接的地址,函數的返回值即是該進(jìn)程數據段所連接的實(shí)際地址,進(jìn)程可以對此進(jìn)程進(jìn)行讀寫(xiě)操作。
使用共享存儲來(lái)實(shí)現進(jìn)程間通信的注意點(diǎn)是對數據存取的同步,必須確保當一個(gè)進(jìn)程去讀取數據時(shí),它所想要的數據已經(jīng)寫(xiě)好了。通常,信號量被要來(lái)實(shí)現對共享存儲數據存取的同步,另外,可以通過(guò)使用shmctl函數設置共享存儲內存的某些標志位如SHM_LOCK、SHM_UNLOCK等來(lái)實(shí)現。
linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)
評論