1.共享内存原理
在Linux中,每个进程都有属于自己的进程控制块(PCB)和地址空间(Addr Space),并且都有一个与之对应的页表,负责将进程的虚拟地址与物理地址进行映射,通过内存管理单元(MMU)进行管理。两个不同的虚拟地址通过页表映射到物理空间的同一区域,它们所指向的这块区域即共享内存。

2.共享内存的创建
int shmget(key_t key, size_t size, int shmflg);
- key:共享标识符,标识系统的唯一IPC资源。
- size:需要申请共享内存的大小。在操作系统中,申请内存的最小单位为页,一页是4k字节,为了避免内存碎片,我们一般申请的内存大小为页的整数倍。
- shmflg:如果要创建新的共享内存,需要使用IPC_CREAT,IPC_EXCL,如果是已经存在的,可以使用IPC_CREAT或直接传0。
- 返回值:成功时返回一个新建或已经存在的的共享内存的操作句柄,失败返回-1并设置错误码。
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<sys/shm.h>
4 #define key 0x89898989
5 int main()
6 {
7
8 int shmid=shmget(key,1024,IPC_CREAT);
9 if(shmid<0)
10 {
11 perror("shmget");
12 return -1;
13 }
14 //
15 return 0;
16
17 }
查看共享内存信息:
ipcs -m

3.共享内存附加到进程(通过共享内存的读写操作)
void *shmat(int shmid, const void *shmaddr, int shmflg);
- shmid:共享内存操作句柄。
- shmaddr:附加共享内存的虚拟地址,当传递NULL值时,系统将自动分配一段未被使用的共享区的地址。
- shmflg:SHM_RDONLY位,则以只读方式连接此段,否则以读写方式连接此段。
- 返回值:成功返回共享内存附加到共享区的地址,并且内核将使其与该共享存储段相关的shmid_ds结构中的shm_nattch计数器加1(类似于引用计数);出错返回-1。
将共享内存附加到test.c文件,作为输入文件,通过指针lp将“linux”传入共享内存中去
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<sys/shm.h>
4 #include <string.h>
5
6 #define key 0x88888888
7
8 int main()
9 {
10
11 int shmid=shmget(key,1024,IPC_CREAT|0644);
12 if(shmid<0)
13 {
14 perror("shmget");
15 return -1;
16 }
17 //
18 void* lp=shmat(shmid,NULL,0);
19 printf("%p\n",(char *)lp);
20 strcpy((char*)lp, "linux");
21 return 0;
22
23 }
将共享内存附加到read.c,作为读端,将“linux”从共享内存中读出
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<sys/shm.h>
4 #include <string.h>
5 #define key 0x88888888
6 int main()
7 {
8
9 int shmid=shmget(key,1024,IPC_CREAT|0644);
10 if(shmid<0)
11 {
12 perror("shmget");
13 return -1;
14 }
15 //
16 void* lp=shmat(shmid,NULL,0);
17 printf("%p\n",(char *)lp);
18 printf("%s\n",lp);
19
20 return 0;
21
22 }
运行结果:

**注意:**与管道不同的是,共享内存是访问,之中的值并不会被拷走!!!
3.共享内存和进程分离
int shmdt(const void *shmaddr) ;
- shmaddr:chmat的返回值
分离之前附加了两个进程:
将read.c加上分离语句:
shmdt(lp);
分离之后只剩一个进程:

3.共享内存的操作
int shmct1(int shmid,int cmd,struct shmid_ds *buf);
- shmid :共享操作句柄
- cmd : 告诉shmctl函数需要做什么操作
- IPC_STAT :获取当前共享内存的属性信息,放在buf当中,buf是出参
- IPC_SET :设置共享内存的属性信息,是用buf来进行设置的buf是入参
- IPC_RMID:删除共享内存,buf可以直接传递为NULLbuf :共享内存的结构体
- buf:共享内存结构体:

注意: 删除共享内存,当使用shmctl或者使用ipcrm,删除共享内存之后,共享内存就实际被释放掉了,当共享内存被释放掉之后,共享内存的标识符会被设置成为0x00000000,表示其他进程不能通过之前的标识符找到该共享内存,并且共享内存的状态会被设置成为dest(destroy),但是还是有进程在附加着共享内存,当前描述共享内存的结构体并没有被释放,直到当前共享内存的附加进程数量为0的时候才会被释放掉。
本文介绍Linux共享内存机制,包括原理、创建方法及进程间的共享内存读写操作。还讲解了如何通过系统调用实现共享内存的附加与分离。
共享内存剖析&spm=1001.2101.3001.5002&articleId=109489107&d=1&t=3&u=7627c37d0d5a4b70b19d321fe5c6054e)
2330

被折叠的 条评论
为什么被折叠?



