程序通訊之共享記憶體:在通訊的程序之間存在一塊可直接訪問的共享空間,通過對這片共享空間進行寫/讀操作實現程序之間的資訊交換。
共享儲存是程序通訊中最靈活,速度最快的通訊方式。因為掛接到同一塊記憶體區域的兩個程序可以直接訪問記憶體區域。而其他幾種方式需要拷貝到核心,再從核心拷貝出去,進行通訊。
需要注意的是,使用者程序空間一般都是獨立的,要想讓兩個使用者程序共享空間必須通過特殊的系統呼叫實現,而程序內的執行緒是自然共享程序空間的。
需要用到的函式有:
1、獲得乙個共享記憶體的識別符號
#include
int shmget(key_t key, size_size, int flags);引數key是唯一標識,可以由ftok函式產生
引數size是該共享儲存段的長度(單位:位元組)。實現通常將其向上取為系統頁長的整數倍。但是,若應用指定的size值並非系統頁長的整數倍,那麼最後一頁的餘下部分是不可使用的。如果正在建立乙個新段(一般是在伺服器程序中),則必須指定其size。如果正在引用乙個現存的段(乙個客戶程序),則將size指定為0。當建立一新段時,段內的內容初始化為0。
引數flags指定建立共享記憶體段的方式,是新建還是引用。
2、shmctl函式對共享儲存段執行多種操作。
include
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
//返回值:若成功則返回0,若出錯則返回-1cmd引數指定下列5中命令中一種,使其在shmid指定的段上執行。
ipc_stat取此段的shmid_ds結構,並將它存放在由buf指向的結構中。
ipc_set按buf指向結構中的值設定與此段相關結構中的下列三個字段:shm_perm.uid、shm_perm.gid以及shm_perm.mode。此命令只能由下列兩種程序執行:一種是其有效使用者id等於shm_perm.cuid或shm_perm.uid的程序;另一種是具有超級使用者特權的程序。
ipc_rmid從系統中刪除該共享儲存段。因為每個共享儲存段有乙個連線計數(shmid_ds結構中的shm_nattach欄位),所以除非使用該段的最後乙個程序終止或與該段脫節,否則不會實際上刪除該儲存段。不管此段是否仍在使用,該段識別符號立即被刪除,所以不能再用shmat與該段連線。此命令只能由下列兩種程序執行:一種是其有效使用者id等於shm_perm.cuid或shm_perm.uid的程序,另一種是具有超級使用者特權的程序。
3、建立了乙個共享儲存段,程序就可呼叫shmat將其連線到它的位址空間中。
include
void *shmat(int shmid, const void *addr, int flag);
//返回值:若成功則返回指向共享儲存的指標,若出錯則返回-1共享儲存段連線到呼叫程序的哪個位址上與addr引數以及在flag中是否指定shm_rnd位有關。
如果addr為0,則此段連線到由核心選擇的第乙個可用位址上。這是推薦的使用方式。
如果addr非0,並且沒有指定shm_rnd,則此段連線到addr所指定的位址上。
如果addr非0,並且指定了shm_rnd,則此段連線到(addr-(addr mod ulus shmlba))所表示的位址上。shm_rnd命令的意思是「取整」。shmlba的意思是「低邊界位址倍數」,它總是2的乘方。該算式是將位址向下取最近1個shmlba的倍數。
除非只計畫在一種硬體上執行應用程式(這在當今是不大可能的),否則不應指定共享段所連線到的位址。所以一般應指定addr為0,以便由核心選擇位址。
如果在flag中指定了shm_rdonly位,則以唯讀方式連線此段。否則以讀寫方式連線此段。
shmat的返回值是該段所連線的實際位址,如果出錯則返回-1。如果shmat成功執行,那麼核心將使該共享儲存段shmid_ds結構中的shm_nattach計數器值加1.
當對共享儲存段的操作已經結束時,則呼叫shmdt脫接該段。注意,這並不從系統中刪除其識別符號以及資料結構。該識別符號仍然存在,直至某個程序(一般是伺服器程序)呼叫shmctl(帶命令ipc_rmid)特地刪除它。
4、取消掛接
include
int shmdt(void *addr);
//返回值:若成功則返回0,若出錯則返回-1addr引數是以前呼叫shmat時的返回值。如果成功,shmdt將使相關shmid_ds結構中的shm_nattach計數器值減1。
附測試**:
//makefile
cli=client
cc=gcc
ser=server
sersrc=comm.c server.c
clisrc=comm.c client.c
.phony:all
all:$(cli) $(ser)
$(cli):$(clisrc)
$(cc) -o $@ $^
$(ser):$(sersrc)
$(cc) -o $@ $^
.phony:clean
clean:
rm -f $(cli) $(ser)
#ifndef _comm_
#define _comm_
#include
#include
#include
#include
#define pathname "."
#define projid 0x6666
#define size 4096*1
int creatshm();
int getshm();
int destoryshm(int shmid);
#endif
#include"comm.h"
static int commshm(int flags)
//shmget函式獲取共享儲存識別符號id
int shmid = shmget(_k, size, flags);
if(shmid < 0)
return shmid;
}int getshm()
int creatshm()
int destoryshm(int shmid)
return 0;
}#include "comm.h"
int main()
//shmdt函式進行去掛接操作
shmdt(mem);
destoryshm(shmid);
return 0;
}#include "comm.h"
int main()
shmdt(mem);
return 0;
}
程序通訊之共享記憶體
1.共享記憶體 1.1.共享記憶體 共享記憶體是在兩個正在執行的程序之間傳遞資料的一種非常有效的方式。共享記憶體允許兩個不相關的程序訪問同乙個邏輯記憶體。由於它並沒有提供同步機制,所以我們通常需要用其他的機制來同步訪問共享的記憶體。共享記憶體是由ipc為程序建立的乙個特殊的位址範圍,它將出現在該程序...
程序間通訊之共享記憶體
此程式實現兩個普通程序間通過共享記憶體來進行通訊,共享記憶體能夠進行大資料量的通訊,這一點事訊息佇列無法比擬的。在這裡同時使用了訊號量來保證兩個程序間的讀寫同步。傳送端源 include include include include include include include include ...
Linux程序通訊之共享記憶體
一 建立共享記憶體,使用shmget函式 int shmget key tkey,int size,int shm 返回值 如果成功,返回共享記憶體段識別符號。如果失敗,則返回 1 errno einval 無效的記憶體段大小 eexist 記憶體段已經存在,無法建立 eidrm 記憶體段已經被刪除...