linux中进程间通信的方法有不少,一般的进程间通信是通过linux内核来完成的,每次信息的交流都先传递给内核,由内核在转给另外一个进程。因此在执行过程中,不断的由用户态到内核态,再由内核态到用户态,消耗的资源非常大。
因此共享内存的出现大大的解决了这个问题,共享内存的实现仅仅在开始从内核中申请一段内存,借助这块内存,之后全部都是在用户态下完成的,由于不再由资源转换方面的浪费,使得进程间通信的速率得到的很大的提高。
可是说共享内存是最快的进程间通信方法。
共享内存
本质
申请了一块物理内存分别映射到N个进程虚拟地址空间,是几种进程间通信方式中性能最好的
特性
- 能够应用于任意进程之间
- 双向通行,每一个进程即可以读,也可以写
- 没有面向字节流或者面向数据块的概念,随机访问内存中的数据
- 没有内置同步互斥
- 声明周期属于内核
API
- 创建
shmget
int shmget(key_t key, size_t size, int shmflg);
key
是申请共享内存的关键字;size
表示想要申请多大的内存,默认是按照4k进行分配的,如果是打开的话一般填0即可;shmflg
表示方法,创建使用IPC_CREAT | 0644
,打开使用0
。
- 挂接
shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);
使用起来类似于malloc
,参数shmif
表示已经打开的共享内存,shmaddr
表示你要挂载的地方,一般填NULL
表示有系统自动分配,shmflg
目前没有什么作用,填0即可。返回值为挂在区域的首地址。
- 卸载
int shmdt(const void *shmaddr);
直接将调用shmat
后所得到的挂载区域首地址(即返回值)作为参数即可。
shmdt使用起来类似free,进程结束系统系统会自动的进行shmdt
- 销毁 shectl
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数shmid
为打开的共享内存id,cmd
为操作码,删除的话填入IPC_RMID
,最后一个参数填0即可,暂时不关注。
演示代码
共有4部分:创建共享内存create,销毁共享内存destroy,读共享内存read,写共享内存。
shmcreate.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main()
{
int shmid = shmget(1234, 100, IPC_CREAT|0644);
if(shmid < 0 ){
perror("shmget");
return 1;
}
printf("shared memory is create success...\n\n");
return 0;
}
shmdestroy.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
int shmid = shmget(1234, 0, 0);
if(shmid < 0 ){
perror("shmget");
return 1;
}
shmctl(shmid, IPC_RMID, 0);
return 0;
}
read.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main(){
//1.打开共享内存
int shmid = shmget(1234, 0, 0);
if(shmid < 0){
perror("shmget open");
return 1;
}
//2.挂载共享内存
char *shm = (char *)shmat(shmid, NULL, 0);
if(shm == NULL) {
perror("shmat");
return 1;
}
//3.读写数据
char buf[1024];
memset(buf, sizeof(buf), 0);
int flag = 1;
while(flag){
printf("[1] continue [0] exit:");
scanf("%d",&flag);
if(flag == 0)
break;
strcpy(buf, shm);
printf("read: [%s]\n",buf);
}
//4.卸载共享内存
shmdt(shm);
return 0;
}
write.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
int shmid = shmget(1234, 0, 0);
if(shmid < 0 ){
perror("shared memory oper");
return 1;
}
char* shmaddr =(char *) shmat(shmid, NULL, 0);
if(shmaddr == NULL){
perror("shmat");
return 1;
}
char buf[1024];
memset(buf, sizeof(buf), 0);
strcpy(shmaddr, "1234");
while(1)
{
printf("write[ exit:1 ]: ");
scanf("%s",buf);
printf("[buf]:%s\n",buf);
if( strcmp(buf,"1")==0 )
break;
strcpy(shmaddr, buf);
printf("write succrss!\n");
}
shmdt(shmaddr);
return 0;
}