Linux:进程间通信——共享内存
发布日期:2021-05-07 02:16:06 浏览次数:24 分类:精选文章

本文共 3164 字,大约阅读时间需要 10 分钟。

Linux:进程间通信——共享内存

原理

共享内存的原理是:在物理内存中开辟一段空间,这段物理内存的空间可以被不同的进程附加到自己的共享区中,附加的进程再通过操作共享区来实现数据的交换。在这里插入图片描述

共享内存的创建

知道共享内存的原理以后,接下来我们要关心的问题是怎样创建一个共享内存,Linux中可以用shmget函数来创建共享内存。

函数原型:#include 
int shmget(key_t key,size_t size,int shmflg);参数解释: key:共享内存标识符,这个标识符相当于共享内存的身份证;程序员在第一次创建的时候,可以随意给值,只要和当前操作系统当中的其他的共享内存标识符不重复 size:共享内存的大小,单位字节 shmflag: IPC_CREAT:如果共享内存不存在,则创建IPC_EXCL: 需要搭配IPC_CREAT一起使用,使用按位或 例子:IPC_CREAT|IPC_EXCL:如果想要获取的共享内存已经存在,则报错,如果想要获取的共享内存是刚刚创建出来的,则返回操作句柄 返回值:返回共享内存的操作句柄

代码:

#include 
#include
#include
#define KEY 0X99999999 int main() { int shmid = shmget(KEY,1024,IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } else { printf("creat success!\n"); } while(1) { sleep(1); } return 0; }

创建完成之后用ipcs -m命令查看

在这里插入图片描述

shmid 拥有者 权限 字节 nattch 状态
0x99999999 32768 dev 664 1024 0

其中shimid表示共享内存操作句柄,nattch表示的是附加的进程数目

将共享内存附加到进程

创建了共享内存之后我们需要做的就是把共享内存附加到进程了,可以使用shmat函数来实现

函数原型:#include 
void *shmat(int shmid,const void *shmaddr,int shmflg);参数说明: shmid:操作句柄 shmaddr:附加到共享内存的什么虚拟地址,允许传递NULL值,让操作系统帮我们选择附加到共享内存的那个地址,这个地址通过该函数的返回值返回给我们 shmflg: SHM_RDONLY:规定当前进程只能对共享内存进程读操作 0:可读可写 返回值:返回共享内存附加到共享内存的地址

代码:

shared.c

#include 
#include
#include
#include
#define KEY 0x89898989int main(){ int shmid = shmget(KEY, 1024, IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } void* lp = shmat(shmid, NULL, 0); strcpy((char*)lp, "hello world!\n"); while(1) { sleep(1); } return 0;}

read.c

#include 
#include
#include
#include
#define KEY 0x89898989int main(){ int shmid = shmget(KEY, 1024, IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } void* lp = shmat(shmid, NULL, 0); printf("%s\n", (char*)lp); return 0;}

shared.c运行结果:

在这里插入图片描述
read.c运行结果:
在这里插入图片描述

将共享内存和进程分离

函数原型:int shmdt(const void *shmaddr);参数解释:	shmaddr:shmat的返回值

shared.c

#include 
#include
#include
#include
#define KEY 0x89898989int main(){ int shmid = shmget(KEY, 1024, IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } void* lp = shmat(shmid, NULL, 0); strcpy((char*)lp, "hello world!\n"); while(1) { sleep(1); } return 0;}

还是上面的程序,当我们把分离函数加上去以后,就分离了一个进程,nattch的值就会-1。

操作共享内存

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

使用这个函数也可以删除共享内存,当我们使用这个函数或者ipcrm删除共享内存后我们会发现:

(1)当使用shmctl或者ipcrm删除共享内存之后,共享内存实际上已经被释放了
(2)共享内存释放掉之后,共享内存的标识符就会被设置成为0X00000000,表示其他进程不能通过之前的标识符找到该共享内存,并且内存的状态也会被设置成dest(如果共享内存已经被释放了,但是还有进程附加着共享内存,当前描述共享内存的结构体并没有被释放,只有当前共享内存的附加进程数量为0的时候才会被释放)
释放后

shmid 拥有者 权限 字节 nattch 状态
0x00000000 32768 dev 664 1024 0 dest

其中shimid表示共享内存操作句柄,nattch表示的是附加的进程数目

上一篇:Linux:多线程简介
下一篇:Linux:进程间通信——命名管道

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2025年03月21日 19时05分13秒