【Linux】进程间通信----共享内存

共享内存,顾名思义就是多个进程共用同一块物理内存;这块物理内存被映射到不同进程的地址空间中进行通信,A进程可以及时看到B进程对共享内存中数据的更新,反之亦然。
这里写图片描述
不同的进程可以直接读写内存,所以它最大的特点就是效率高,但是共享内存本身不带任何同步互斥机制,所以当多个进程同时对共享内存操作时会破坏内容,所以,我们使用共享内存通信时候,同步互斥机制要我们用户自己来完成。

共享内存特点:

1. 没有同步互斥机制
2. 全双工
3. 用于任意进程
4. 生命周期随内核

相关函数:
1.
//创建共享内存
int shmget(key_t key,size_t size,int shmflg);

参数:
key:共享内存段名字;
size:共享内存的大小,(注意:这里的大小是一页的大小,1页=4k,所以这里的大小是1024的整数倍);
shmflg:由9个权限标志位组成,用法与消息队列相同;

2
//挂接共享内存与当前进程
void* shmat(int shmid,const void* shmaddr,int shmflg);
//取消共享内存与当前进程的挂接
int shmdt(const void* shmddr);

参数:
shmid:共享内存标识;
shmddr:指定连接的地址;
shmflg:两个可能取值是SHM_RND和SHM_RDONLY(只读共享内存);
返回值:返回一个指针,指向共享内存的第一个节,失败返回-1;

4
//控制共享内存
int shmctl(int shmid,int cmd,struct shmid_ds *buf);

参数:
shmid:共享内存标识;
cmd:要采取的三个动作(三个值可选,IPC_STAT,IPC_RMID,IPC_SET);
buf::指向⼀个保存着共享内存的模式状态和访问权限的数据结构(可设置为NULL);
返回值:成功返回0,失败返回1;

例子:client和server使用共享内存通信代码

//server.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>

#define PATH_NAME "/tmp"
#define PATH_ID 0X6666

int main()
{
  key_t k = ftok(PATH_NAME,PATH_ID);  //创建标识符
  if(k < 0)
  {
    printf("ftok error!\n");
    return -1;
  }

 int  shmid = shmget(k,4*1024,IPC_CREAT|IPC_EXCL|0x666);  //开辟共享内存
  if(shmid < 0)
  {
    printf("shmget error!\n");
  }

  char* ptr = (char*)shmat(shmid,NULL,0);  //挂接共享内存
  while(1)
  {
    printf("%s\r",ptr);
    fflush(stdout);
    sleep(1);
  }

  shmdt(ptr); //取消挂接共享内存
  shmctl(shmid,IPC_RMID,NULL);
  return 0;
}
//client.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>

#define PATH_NAME "/tmp"
#define PATH_ID 0X6666

int main()
{
  key_t k = ftok(PATH_NAME,PATH_ID);  //创建标识符
  if(k < 0)
  {
    printf("ftok error!\n");
    return -1;
  }

 int  shmid = shmget(k,4*1024,IPC_CREAT);  //开辟共享内存
  if(shmid < 0)
  {
    printf("shmget error!\n");
  }

  char* ptr = (char*)shmat(shmid,NULL,0);  //挂接共享内存

  int x = 'A';
  for(;x<='Z';++x)
  {
    ptr[x-'A'] = x;
    ptr[x-'A'+1] = '\0';
    sleep(1);
  }

  shmdt(ptr); //取消挂接共享内存
  return 0;
}

查看一下系统共享内存资源:
这里写图片描述
注意:shmdt()是取消挂接,并不是删除共享内存;
删除共享内存可以调用shmctl()函数,也可以使用命令:ipcrm -m 标识符

运行结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/prefect_boy/article/details/80399114