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

1、概念
共享内存允许两个不相干的进程访问同一个逻辑内存。
共享内存是最快的IPC形式。省略了两次拷贝,不再涉及到内核,进程不再通过通过执行内核中的系统调用来传递彼此的数据。共享内存的生命周期随内核。
优点:
1)数据的共享使进程间的数据不用相互的传递,而是直接通过访问内存,加快了效率。
缺点
1)共享内存没有同步与互斥机制,我们需要用其他方法进行进程间的同步机制。
我们需要借助互斥量或者信号量来完成进程的同步与互斥,在这里说一下互斥量和信号量 。互斥量用于线程的互斥,信号量用于线程的同步。
2)没有同步也就是说当一个程序对共享内存进行操作的时候,并没有自动机制去阻止第二个程序去操作它。不同进程之间共享的是同一段物理内存,所以也会导致进程之间相互的产生影响。
3)共享内存并不会随着进成的退出的而退出,因此我们在最后不使用该空间时,必须手动的去删除。
2、共享内存函数:
shmget函数

功能:用来创建共享内存 原型:
int shmget(key_t key,size_t size,int shmflg);
参数:
key:这个共享内存段名字
size:共享内存大小(通常以页为单位)
shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的。
返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1;

shmat函数

功能:讲共享内存段连接到进程地址空间。
原型:
void *shmat(int shmid ,const void *shmaddr,int shmflg);
参数:
shmid:共享内存标识;
shmaddr:指定连接的地址
shmflg:它的两个可能取值是:SHM_RND和SHM_RDONLY
返回值:成功返回一个指针,指向共享内存的第一个节,失败返回的是-1

shmdt函数

功能:将共享内存段与当前进程进行脱离
原型
int shmdt(const void *shmaddr);
参数:
shmaddr:由shmat所返回的指针
返回值:成功返回的是0,失败返回的是-1;
注意:将共享内存段与当前进程脱离不等于删除共享内存段

shmctl函数

功能:用于控制共享内存
原型:
int shmctl(int shmid ,int cmd, struct shmid_ds *buf);
参数:
shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作(有三个可能值)
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0,失败返回-1

命令 说明
IPC_STAT 把shmid_ds结构中的数据设置为共享内存的当前关联值
IPC_SET 在进程有足够权限的前提下,把共享内存的当前关联值设置为shmid_ds数据结构中给出的值
IPC_RMID 删除共享内存段

Makefile的实现:

1 .PHONY:clean
  2 all:server client
  3 
  4 client:client.c  comm.c
  5     gcc  -o  $@ $^
  6 server:server.c comm.c
  7     gcc -o $@ $^
  8 .PHONY:clean
  9 clean:
 10     rm -f client server
 11 
~                   

comm.h的实现

1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/ipc.h>
  4 #include <sys/shm.h>
  5 
  6 #define PATHNAME "."
  7 #define PROJ_ID 0X6666
  8 
  9 int createShm(int size);
 10 int destroyShm(int shmid);
 11 int getShm(int size);

comm.c的实现:

 1 #include "comm.h"
  2 
  3 static int commShm(int size,int flags)
  4 {
  5     key_t _key=ftok(PATHNAME,PROJ_ID);
  6     if(_key<0){
  7     perror("ftok");
  8     return -1;
  9     }
 10     int shmid=0;
 11     if((shmid=shmget(_key,size,flags))<0){
 12     perror("shmget");
 13     return -2;
 14     }
 15     return shmid;
 16 }
 17 
 18 
 19 int destroyShm(int shmid)
 20 {
 21     if(shmctl(shmid,IPC_RMID,NULL)<0){
 22     perror("shmctl");
 23     return -1;
 24     }
 25     return 0;
 26 }
 27 
 28 int createShm(int size){
 29     return commShm(size,IPC_CREAT|IPC_EXCL|0666);
 30 }
 31 
 32 int getShm(int size)
 33 {
 34     return commShm(size,IPC_CREAT);
 35 }
 36 

server.c的实现

 1 #include "comm.h"
  2 int main()
  3 {
  4     int shmid=createShm(4096);
  5     char *addr=shmat(shmid,NULL,0);
  6     sleep(2);
  7     int i=0;
  8     while(i++<26){
  9     printf("client# %s\n",addr);
 10     sleep(1);
 11     }
 12     shmdt(addr);
 13     sleep(2);
 14     destroyShm(shmid);
 15     return 0;
 16 }
 17 

client.c的实现

1 #include "comm.h"
  2 
  3 int main()
  4 {
  5     int shmid=getShm(4096);
  6     sleep(1);
  7     char *addr=shmat(shmid,NULL,0);
  8     sleep(2);
  9     int i=0;
 10     while(i++<26){
 11     addr[i]='A'+i;
 12     i++;
 13     addr[i]=0;
 14     sleep(1);
 15     }
 16     shmdt(addr);
 17     sleep(2);
 18     return 0;
 19 }

我在后期执行结构是正确的但是但我第二次在进行执行的时候,我发现和以前的几种进程间通信的例子都是一下那个痛的,发现文件这是已经存在了,这时候我们就必须尝试的进行删除文件。可是我在删除文件的时候遇到的困难就是删除不了,刚开始,我以为是因为权限的问题,在修改完之后,依然还有删除不了的问题,这个问题在这里一直没解决了。后期我会尝试去努力的解决掉这个问题。

猜你喜欢

转载自blog.csdn.net/daboluo521/article/details/80039888
今日推荐