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