您好,登錄后才能下訂單哦!
共享內存
進程間通信的本質是讓不同的進程訪問一塊公共的資源。
1、共享內存是進程間通信最快的方式(為什么)
2、共享內存不提供任何的同步與互斥關系。(由用戶維護,可以用信號量)
以下圖解釋了問題1,原因是,由于共享內存的機制,兩個進程不需要拷貝拷貝數據,這個特點可能在數據較少的情況下看不出來,但是數據較多時,優勢較為明顯。
下圖是shmat之前之后的共享內存示意圖:(shmget獲得共享內存后需要掛接)
函數:
用于Linux進程通信共享內存。共享內存函數由shmget、shmat、shmdt、shmctl四個函數組成。
shmat(把共享內存區對象映射到調用進程的地址空間)
void *shmat(int shmid, const void *shmaddr, int shmflg)
參數:
shmid | 共享內存標識符 |
shmaddr | 指定共享內存出現在進程內存地址的什么位置,直接指定為NULL讓內核自己決定一個合適的地址位置 |
shmflg | 如果設置為SHM_RDONLY是只讀模式,其他為讀寫模式 |
返回值:成功返回附加好的共享內存地址
shmdt(斷開共享內存連接)
int shmdt(const void *shmaddr)
參數:
shmaddr:連接的共享內存的起始地址
返回值:成功返回0
shmget(得到一個共享內存標識符或創建一個共享內存對象)
int shmget(key_t key, size_t size, int shmflg)
參數:
key | 大于0的32位整數:視參數shmflg來確定操作。通常要求此值來源于ftok返回的IPC鍵值 |
size | 大于0的整數:新建的共享內存大小,以字節為單位 |
flags | 有IPC_CREAT和IPC_EXCL(用法同前面寫的一致) |
返回值:成功返回共享內存標示符
注:system V分配內存的方法以頁為基本單位,一般以頁的整數倍分配。
shmctl完成對共享內存的控制
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
參數:
shmid | 共享內存標識符 | |
cmd | IPC_STAT:得到共享內存的狀態,把共享內存的shmid_ds結構復制到buf中 | |
IPC_SET:改變共享內存的狀態,把buf所指的shmid_ds結構中的uid、gid、mode復制到共享內存的shmid_ds結構內 | ||
IPC_RMID:刪除這片共享內存 | ||
buf | 共享內存管理結構體。具體說明參見共享內存內核結構定義部分 |
共享內存實現通信的例子
comm.h
#pragma once #include<errno.h> #include<sys/ipc.h> #include<sys/shm.h> #include<string.h> #define _PATH_NAME_ "/temp" #define _PROJ_ID_ 0x6666 int create_shm(int size); int get_shm(); int destory_shm(int shm_id); void* shm_at(int shm_id); int shm_dt(void*shmaddr);
comm.c
#include"comm.h" static int comm_create_shm(int size,int flags) { key_t _key = ftok(_PATH_NAME_,_PROJ_ID_); if(_key<0) { perror("ftok"); return -1; } // int shm_id=shmget(_key,size,IPC_CREAT | IPC_EXCL); int shm_id=shmget(_key,size,flags); if(shm_id < 0) { perror("shmget"); return -2; } return shm_id; } int create_shm(int size) { int flags = IPC_CREAT | IPC_EXCL|0666; return comm_create_shm(size,flags); } int get_shm() { int flags = IPC_CREAT; return comm_create_shm(0,flags); } int destory_shm(int shm_id) { if(shmctl(shm_id,IPC_RMID,NULL)<0) { perror("shmctl"); return -1; } return 0; } void* shm_at(int shm_id) { return shmat(shm_id,NULL,0); } int shm_dt(void* shmaddr) { return shmdt(shmaddr); }
server.c
#include"comm.c" int main() { int shm_id = create_shm(4096); sleep(5); char* buf = (char*)shm_at(shm_id); sleep(1); sleep(1); while(1) { printf("%s\n",buf); sleep(1); if(strcmp(buf,"AAAAA") == 0) { break; } } shm_dt(buf); sleep(5); destory_sem(sem_id); return 0; }
client.c
#include"comm.c" int main() { int shm_id = get_shm(); char* buf = (char*)shm_at(shm_id); int index = 0; while(1) { buf[index++]='A'; buf[index]='\0'; sleep(1); if(index>5) { break; } } sleep(5); shm_dt(buf); sleep(5); return 0; }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。