c++ fork 进程时 共享内存_c/c++ Linux 进程间通信------共享内存
1. 什么是共享內存
共享內存(Shared Memory),指兩個或多個進程共享一個給定的存儲區。進程可以將同一段共享內存連接到它們自己的地址空間中,所有進程都可以訪問共享內存中的地址,就好像它們是由用C語言函數malloc分配的內存一樣。而如果某個進程向共享內存寫入數據,所做的改動將立即影響到可以訪問同一段共享內存的任何其他進程。
個人理解:在物理內存上有一塊空間,不同的進程通過頁表將其映射到自己的虛擬地址空間,返回一個地址,通過這個地址可以訪問到那一塊內存空間,此內存空間為共享內存;
2. 原理
下圖中紅線表示不同進程將自己的地址空間映射到不同物理內存中,各自進行自己的任務,不同進程之間獨立工作
不同進程通過共享內存進行通信:
在物理內存上開辟一塊空間,稱為共享內存
不同進程將這塊共享內存連接到自己的地址空間
不同進程以各自地址空間的虛擬地址通過頁表找到共享內存,通過向共享內存中寫數據和讀數據實現進程間通信
3. 共享內存的特點
以傳送數據為目的
所有進程間通信中速度最快的一種方式(例:進程一向共享內存傳送數據,進程二能夠立馬看見傳送的數據,少了若干次拷貝)
共享內存生命周期隨內核
共享沒有自帶同步或互斥,由用戶來維護共享內存
信號量+共享內存通常結合在一起使用,信號量用來同步對共享內存的訪問
4. 共享內存的操作
共享內存的創建
#include
#include
//如果共享內存不存在,創建共享內存,如果存在就打開共享內存
int shmget(key_t key, size_t size, int shmflg);
//返回值:成功返回共享內存的標識符,失敗返回-1
參數:共享內存的關鍵字key
共享內存的標識符,獲取方法和消息隊列 key的方法一致,也可認為key就是共享內存的名字
參數:共享內存的大小size:
由你自己指定,一般指定為4k的倍數(內存4k為一頁)
參數:共享內存的訪問權限shmflg
共享內存的權限,它與文件的訪問權限一樣
IPC_CREAT:創建新的共享內存。
IPC_EXCL:與IPC_CREAT一同使用,表示如果要創建的共享內存已經存在,則返回錯誤。 IPC_NOWAIT:讀寫共享內存要求無法滿足時,不阻塞
0:如果是打開文件,即文件已存在,寫0
共享內存的查看
命令: ipcs -m
共享內存的掛載
#include
#include
//將共享內存鏈接到進程地址空間
void *shmat(int shmid, const void *shmaddr, int shmflg);
//返回值:失敗返回NULL,成功返回一個指針,為地址空間的虛擬地址,并且連接數加1(nattch)
參數:共享內存的標識符shmid
shmget的返回值
參數:指定連接進程地址空間的地址shmaddr
共享存儲段連接到調用進程的哪個地址上與addr參數以及在flag中是否指定SHM_RND位有關
如果addr為0,則此段連接到由內核選擇的第一個可用地址上。這是推薦的使用方式。
如果addr非0,并且沒有指定SHM_RND,則此段連接到addr所指定的地址上。
如果addr非0,并且指定了SHM_ RND,則此段連接到(shmaddr -(shmaddr % SHMLBA))所表示的地址上。SHM_RND命令的意思是取整。SHMLBA的意思是低邊界地址倍數,它總是2的乘方。該算式是將地址向下取最近1個SHMLBA的倍數。
注:除非只計劃在一種硬件上運行應用程序(這在當今是不大可能的),否則不應指定共享段所連接到的地址。所以一般應指定addr為0,以便由內核選擇地址
參數:共享內存的權限shmflg
shmflg = SHM_RDONLY,表示連接操作作用來只讀共享內存
共享內存的卸載
#include
#include
//將共享內存與當前連接進程脫離
int shmdt(const void* shmaddr)
//返回值:成功返回0,失敗返回-1
//參數:由shmat返回的指針
//注意:將共享內存與進程脫離不等于刪除共享內存
共享內存的控制
#include
#include
//shmctl系統調用對shmid標識的共享內存執行cmd操作
//返回值:成功返回0,失敗返回-1
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
參數:共享內存的表示符shmid
shmget的返回值
參數:將要采取的操作cmd
選項 說明
IPC_STAT 把shmid_ds結構中的數據設置為共享內存的當前關聯值
IPC_SET 在進程有足夠權限的前提下,把共享內存的當前關聯值設置為shmid_ds數 據結構中給出的值
IPC_RMID 刪除共享內存
參數:保存共享內存的模式狀態和訪問權限的數據結構buf
共享內存的一些屬性,填NULL
服務端客戶端實例
comm.h
#ifndef __COMM_H__
#define __COMM_H__
#include
#include
#include
#define PATHNAME "."
#define PROJ_ID 0x6666
int createShm(int size);//創建共享內存
int getShm(int size);//獲取共享內存
int destoryShm(int shmid);//銷毀共享內存
#endif
comm.c
#include "comm.h"
static int commShm(int size,int flags)//創建共享內存
{
key_t key = ftok(PATHNAME,PROJ_ID);
if(key < 0){
perror("ftok");
return -1;
}
int shmid = shmget(key, size, flags);
if(shmid < 0){
perror("shmget");
return -2;
}
return shmid;
}
int createShm(int size)
{
return commShm(size, IPC_CREAT | IPC_EXCL);
}
int getShm(int size)//獲取共享內存
{
return commShm(size, IPC_CREAT);
}
int destoryShm(int shmid)//銷毀共享內存
{
if(shmctl(shmid, IPC_RMID,NULL) < 0){
perror("shmctl");
return -3;
}
}
server.c
#include "comm.h"
int main()
{
int shmid = createShm(4096);//創建共享內存
char* addr = (char*)shmat(shmid,NULL,0);//將共享內存進行掛接
int i=0;
while(i++ < 26){
printf("client:%s
總結
以上是生活随笔為你收集整理的c++ fork 进程时 共享内存_c/c++ Linux 进程间通信------共享内存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Easy2d 文档教程之 Visual
- 下一篇: Linux操作系统安装字体笔记