共享內存:使得多個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運⾏效率較低⽽設計的。往與其它通信機制,如信號量結合使用,來達到進程間的同步及互斥。共享內存效率高,因爲不像管道以及消息隊列一樣,讀寫時進行拷貝兩次,而共享內存直接進行內存讀寫,不需要進行拷貝。共享內存申請的空間內存在堆棧之間。生命週期爲隨內核。
32位平臺下一個進程認爲自己的地址空間爲4G,0~3G爲用戶區,3~4G爲內核區。
在驗證共享內存中我們會涉及到一些函數,下面對這些函數進行一一解釋:
1、申請共享內存——shmget()函數
函數原型:int shmget(key_t key,size_t size,int shmflg);
第一個參數,程序需要提供一個參數key,有效的爲共享內存段命名,key_t key=ftok(PATHNAME,PROJ_ID);
第二個參數:申請共享內存的大小,以字節爲單位。(一般是4096的整數倍)
第三個參數:權限標誌,IPC_CREAT|IPC_EXCL:若共享內存存在便出錯返回,若不存在則創建之,IPC_CREAT:若共享內存存在便打開返回,若不存在則創建之。
返回值:返回用戶可使用的共享內存標誌符。
2、釋放共享內存——shmctl()函數
函數原型:int shmctl(int shmid,int cmd,struct shmid_ds *buf);
第一個參數:shmget函數返回的共享內存標識符
第二個參數:要使用的操作,此處爲IPC_RMID,表示刪除。
第三個參數:buf對應的結構指針:
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
3、將共享內存掛接到進程的地址空間——shmat()函數
函數原型:void* shmat(int shmid,const void* shmaddr,int shmflg)
第二個參數:一般爲空。
第三個參數:一般爲0。
4、去關聯——shmdt()函數
函數原型:int shmdt(const void* shmaddr);
參數: shmat()函數的返回值。
源碼驗證:
comm.h:
#ifndef _COMM_H_
#define _COMM_H_
#include<stdio.h>
#include<unistd.h>
#include<error.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#define PATHNAME "."
#define PROJ_ID 0x666
//創建共享內存
int create_shm(size_t size);
int comm_shm(size_t size,int shm_flag);
//銷燬
int destroy_shm(int shmid);
//獲取
int get_shm();
#endif
comm.c:
#include"comm.h"
int comm_shm(size_t size,int shm_flag)
{
key_t key=ftok(PATHNAME,PROJ_ID);
if(key<0)
{
perror("ftok");
return -1;
}
int shmid=shmget(key,size,shm_flag);
if(shmid<0)
{
perror("shmget");
return -2;
}
return shmid;
}
int create_shm(size_t size)
{
return comm_shm(size,IPC_CREAT|IPC_EXCL|0666);
}
int get_shm()
{
return comm_shm(0,IPC_CREAT);
}
int destroy_shm(int shmid)
{
if(shmctl(shmid,IPC_RMID,NULL)<0)
{
perror("shmctl");
return -1;
}
return 0;
}
server.c:
#include"comm.h"
int main()
{
int shmid=create_shm(4096);
char *buf=shmat(shmid,NULL,0);
int count=0;
while(count<4096)
{
buf[count]='A'+count%26;
count++;
sleep(3);
buf[count]=0;
}
shmdt(buf);
destroy_shm(shmid);
return 0;
}
client.c:
#include"comm.h"
int main()
{
int shmid=get_shm();
char* buf=shmat(shmid,NULL,0);
while(1)
{
printf("%s\n",buf);
sleep(3);
}
shmdt(buf);
return 0;
}