SystemV 共享内存(二)—— 共享内存实现不同进程间通信(shmat / shmdt)

共享内存(一)—— 共享内存的创建与释放_abs(ln(1+NaN))的博客-CSDN博客介绍共享内存的定义,及其共享内存的创建函数和释放函数https://blog.csdn.net/challenglistic/article/details/124362340?spm=1001.2014.3001.5501在创建好共享内存以后,我们需要让进程挂接到这块共享内存上通信,涉及到的系统调用是 shmat(挂接)、shmdt(断连),最后会结合之前的所有内容测试服务端和客户端的通信


目录

一、shmat函数(shared memory attach)

1、参数解析

2、返回值解析

二、shmdt函数(shared memory detach)

三、共享内存实现不同进程间通信

1、服务端

2、客户端

3、客户端和服务端通信测试

四、共享内存的特性


一、shmat函数(shared memory attach)

这个函数的作用是将进程挂接到共享内存上。

使用shmget创建或者使用共享内存的时候,都会有一个key值,这个key值会被保存在共享内存的结构体中,进程会带着key值去和所有的共享内存中的key值比对,如果一致,则连接。下面这个是用户层的共享内存结构体信息(内核层的结构体虽然有区别,但是大体都一样)

1、参数解析

下面是挂接函数的函数声明及需要的头文件

第一个参数,当前进程要挂接的共享内存的ID

第二个参数,手动指定要挂接的共享内存的地址。一般设置为NULL,表示让OS自己决定

第三个参数,挂接以后允许的操作。比如只读、只写、可读可写等,一般是设置为0,表示可读可写。

2、返回值解析

成功时,返回当前进程挂接到的共享内存的首地址;失败时返回 -1。类似于malloc函数,如果在堆上开辟空间成功,则返回堆上开辟空间的首地址

二、shmdt函数(shared memory detach)

这个函数的作用是断开当前进程和共享内存之间的连接

参数是当前进程连接的共享内存的地址

返回值:成功返回0,失败返回 -1

三、共享内存实现不同进程间通信

下面我们就接续上一次的内容,实现服务端和客户端之间的通信

1、服务端

服务端包含的内容是创建共享内存、连接共享内存、从共享内存中读取内容、断开联系、释放内存

2、客户端

客户端包含的内容是 使用已经存在的共享内存、连接共享内存、向共享内存中写入内容、断开联系、释放内存

要连接共享内存,就需要知道共享内存的ID——》共享内存的ID需要经过shmget获得,但是shmget既可以创建共享内存,也可以使用共享内存,并获取共享内存的ID ——》shmget的第三个参数是IPC_CREAT,表示当共享内存已经存在时,直接使用这块共享内存

3、客户端和服务端通信测试

一开始只运行服务端,但不运行客户端,我们会发现服务端一直在打印,并不像之前的命名管道,会等待另一个进程的输入,所以共享内存不存在同步机制!!

现在我们开始运行客户端,客户端向共享内存里写入数据,服务端就会打印相应的内容

四、共享内存的特性

第一,共享内存的生命周期是随内核的。当通信的两个进程退出以后,共享内存依然存在,只有当OS关闭或者调用系统函数shmctl,共享内存才会被释放

第二,共享内存不存在同步或者互斥机制,数据安全要自己维护。服务端运行的时候,会立即开始打印,也就是读取,但是读取到的为空,所以直接打印空,根本不会等待另一个进程的输入。

第三,通过共享内存通信的方式是目前进程间通信最快的。之前的read或者write函数的本质都是将数据从内核拷贝到用户,或者将数据从用户拷贝到内核——》但是共享内存无需这么复杂,进程创建并连接到共享内存,进程的地址空间中就会有这块内存的虚拟地址,我们可以把这个地址当作指针使用,直接写入数据即可!!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 在C语言中实现共享内存需要使用操作系统提供的系统调用来创建和访问共享内存。 具体来说,需要使用以下步骤来实现共享内存: 1. 使用shmget()系统调用创建共享内存段。shmget()函数需要传入三个参数:共享内存的key,共享内存大小,以及访问权限。如果共享内存段已经存在,则可以使用shmget()函数获取共享内存段的ID。 2. 使用shmat()系统调用将共享内存段连接到进程的地址空间中。shmat()函数需要传入两个参数:共享内存段的ID和一个地址,如果该地址为空,则系统会自动分配一个地址。 3. 对共享内存段进行读写操作,使用与操作普通内存相同的方法进行访问。 4. 当进程不再需要访问共享内存段时,需要使用shmdt()系统调用将共享内存段与进程断开连接。 5. 当所有进程都断开连接并且不再需要共享内存段时,使用shmctl()系统调用删除共享内存段。 需要注意的是,共享内存的并发控制是非常重要的,需要使用互斥锁或信号量等机制来保证共享内存的正确访问。 ### 回答2: C语言可以使用System V共享内存机制来实现共享内存的使用。 共享内存是一种在进程之间共享数据的方式,可以提高进程间通信的效率。以下是使用C语言实现共享内存的一般步骤: 1. 首先创建共享内存区域。可以使用`shmget`函数来创建共享内存,需要指定共享内存的大小、权限和标识符等参数。 2. 绑定共享内存到当前进程中。可以使用`shmat`函数将共享内存映射到当前进程的地址空间中,通过返回的指针可以访问共享内存区域。 3. 使用共享内存进行数据读写。一旦共享内存区域被映射到进程的地址空间,就可以通过指针对其进行读写操作。当多个进程共享同一块内存时,需要进行同步操作,如使用互斥锁或信号量等机制来避免数据不一致或竞态条件。 4. 分离共享内存。当不再需要使用共享内存时,可以使用`shmdt`函数将共享内存从当前进程中分离,并保留共享内存区域供其他进程使用。 5. 删除共享内存。当所有进程都不再需要使用共享内存时,可以使用`shmctl`函数来删除共享内存区域,释放资源。 需要注意的是,共享内存区域只能用于进程间通信,对于线程间通信来说,并不适用。同时,使用共享内存需要谨慎操作,确保数据的一致性和安全性。 ### 回答3: 在C语言中,可以通过使用共享内存实现不同进程之间的数据共享。下面是一个简单的示例用法: 首先,需要使用`shmget()`函数来创建一个共享内存段。该函数接受三个参数,分别是一个标识符(可以是一个整数值,通常使用IPC_PRIVATE表示),所需内存的大小(字节数),以及标志位(通常为IPC_CREAT | 0666)。 ```c int shmid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0666); ``` 接下来,使用`shmat()`函数将共享内存段附加到当前进程的地址空间。该函数接受两个参数,即共享内存段的标识符以及访问内存段的权限(通常为0)。 ```c int* shared_memory = (int*) shmat(shmid, 0, 0); ``` 现在,可以在程序中使用`shared_memory`指针来访问共享内存。 当共享内存使用完毕后,需要使用`shmdt()`函数将其从进程中分离。 ```c shmdt(shared_memory); ``` 最后,如果不再需要该共享内存段,可以使用`shmctl()`函数进行控制。该函数的第一个参数为共享内存段的标识符,第个参数为控制命令(通常为IPC_RMID),第三个参数为一个`struct shmid_ds*`类型的指针。 ```c shmctl(shmid, IPC_RMID, NULL); ``` 这样,就完成了在C语言中使用共享内存进行进程间数据共享的实现。需要注意的是,共享内存的使用需要谨慎,因为多个进程访问共享内存时必须协调好数据的读写,防止出现数据不一致或竞争条件等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值