IPC共享内存 shm

共享内存是最快的IPC

检查共享内存:ipcs m | grep "name"

删除共享内存:ipcrm m "共享内存ID号"

==========================

测试一:

启动两个程序,创建打开同一块共享内存,

查看一下共享内存情况如下:

root@PLATDEV:~# ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status      

0x00005feb 0          root      666        12000      3                      

0x00005fe7 32769      root      666        524288     2                      

0x00005fe8 65538      root      666        2097152    1                      

0x00004321 131075     root      644        40964      0                      

0x00004333 327684     root      644        16539      0                      

0x0000433f 458757     root      644        16539      0                      

0x000000c8 655367     root      644        1024       2                      

root@PLATDEV:~# ipcrm -m 655367          <------- 通过ipcrm删除该shm

root@PLATDEV:~# ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status      

0x00005feb 0          root      666        12000      3                      

0x00005fe7 32769      root      666        524288     2                      

0x00005fe8 65538      root      666        2097152    1                      

0x00004321 131075     root      644        40964      0                      

0x00004333 327684     root      644        16539      0                      

0x0000433f 458757     root      644        16539      0                      

0x00000000 655367     root      644        1024       2          dest         <--------  注意: (1)该shm key已经变为 0x0    (2)该 shm 的status 已经变成 dest  

                                                                                                                                  (3)之前attach 多少进程依然不变

                                                                                                                               

关闭一个进程后:

root@PLATDEV:~# ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status      

0x00005feb 0          root      666        12000      3                      

0x00005fe7 32769      root      666        524288     2                      

0x00005fe8 65538      root      666        2097152    1                      

0x00004321 131075     root      644        40964      0                      

0x00004333 327684     root      644        16539      0                      

0x0000433f 458757     root      644        16539      0                      

0x00000000 655367     root      644        1024       1          dest      

关闭另一个一个进程后, 共享内存被删除

root@PLATDEV:~#

root@PLATDEV:~# ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status      

0x00005feb 0          root      666        12000      3                      

0x00005fe7 32769      root      666        524288     2                      

0x00005fe8 65538      root      666        2097152    1                      

0x00004321 131075     root      644        40964      0                      

0x00004333 327684     root      644        16539      0                      

0x0000433f 458757     root      644        16539      0    

测试二:

延续上面的测试到

root@PLATDEV:~# ipcrm -m 655367          <------- 通过ipcrm删除该shm

root@PLATDEV:~# ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status      

0x00005feb 0          root      666        12000      3                      

0x00005fe7 32769      root      666        524288     2                      

0x00005fe8 65538      root      666        2097152    1                      

0x00004321 131075     root      644        40964      0                      

0x00004333 327684     root      644        16539      0                      

0x0000433f 458757     root      644        16539      0                      

0x00000000 655367     root      644        1024       2          dest         <--------  注意: (1)该shm key已经变为 0x0    (2)该 shm 的status 已经变成 dest  

                                                                                                                                  (3)之前attach 多少进程依然不变

这个时候再启动一个进程,这个时候会发现这个进程会按照shm key 创建全新的shm (原来的shm key已经清零了, 所以新创建的shm会创建成功)

key        shmid      owner      perms      bytes      nattch     status      

0x00005feb 0          root      666        12000      3                      

0x00005fe7 32769      root      666        524288     2                      

0x00005fe8 65538      root      666        2097152    1                      

0x00004321 131075     root      644        40964      0                      

0x00004333 327684     root      644        16539      0                      

0x0000433f 458757     root      644        16539      0                      

0x00000000 655367     root      644        1024       2          dest        

0x000000c8 655367     root      644        1024      1      <-------- 这里

=======================================

【注意1】:

共享内存的创建和打开和 用户权限有很大关系, 1个用户不能打开其他用户创建的共享内存(甚至是root 用户)

owner: 创建者

perms: 权限设置

在创建共享内存的时候其中有个参数很重要,用作权限设置,

S_IRUSR    0400     创建用户有读权限

S_IWUSR   0200     创建用户有写权限

S_IRGRP    0040     创建用户所属用户组有读权限

S_IWGRP   0020     创建用户所属用户组有写权限

S_IROTH    0004    其他用户有读权限

S_IWOTH   0002    其他用户有写权限

使用用户chaos 登录,创建共享内存 0x00000100 权限0644


切换用户为xcp

打开该共享内存都会失败

修改方法: 权限设置为 0666 就可以了

【注意2】:

原来共享内存权限是 0644(注意是 8进制 ), 后面open 这个共享内存并把权限修改为 0666 实际是不会生效的, 需要删除后重新创建,

说到底就是已经创建的共享内存不能对他的参数做任何修改操作, 除非删除后重新创建。

【注意3】:

创建共享内存的大小较小, 但是往里面写的数据溢出,需要重点注意,

因为溢出数据会写到进程的其他映射的空间,造成在访问这些空间的时候出现不可预知的异常。

=====================================

参考: http://user.qzone.qq.com/89617663/blog/1318849395#!app=2&via=QZ.HashRefresh&pos=1318849395

=====================================

共享内存系统参数(单位:字节)

kernel.shmmni = 4096                      ------ SHMMNI 表示 内共享内存段的最大数量。该参数的默认值是 4096

kernel.shmall = 524288                    ------ SHMALL 表示整个系统共享内存总量(以页为单位)。 该参数的值始终应该至少为:ceil(SHMMAX/PAGE_SIZE)

kernel.shmmax = 1073741824*2      ----- SHMMAX 表示整个系统共享内存总量(以字节为单位, 默认值是 32MB )。 一般使用下列方法之一种将 SHMMAX 参数设为 2GB

# getconf PAGESIZE

4096

ceil(expr)    : 返回大于或者等于 expr 的最小整数

floor(expr)  : 返回小于或者等于 expr 的最小整数


### 共享内存的基本使用方法 共享内存是一种高效的进程间通信(IPC)方式,其核心思想是多个进程通过访问同一块物理内存区域来实现数据交换。在 Windows 平台上,C# 提供了 `MemoryMappedFile` 类来创建和管理共享内存[^1]。 #### 创建共享内存的步骤(以 C# 为例) 1. **创建内存映射文件** 使用 `MemoryMappedFile.CreateOrOpen` 方法可以创建或打开一个共享内存对象。可以通过指定名称让多个进程访问同一块内存。 2. **创建视图访问器** 通过 `MemoryMappedViewAccessor` 或 `MemoryMappedViewStream` 来访问共享内存中的数据。前者适合直接读写基本类型数据,后者适合处理复杂结构或大量数据。 3. **跨进程访问共享内存** 在另一个进程中,使用相同的名称调用 `MemoryMappedFile.OpenExisting` 来获取已存在的共享内存对象,并通过视图访问器读写数据。 #### 示例代码(C#) ```csharp // 进程A:创建共享内存并写入数据 using System; using System.IO.MemoryMappedFiles; class Program { static void Main() { // 创建或打开名为 "MySharedMemory" 的共享内存 using (var mmf = MemoryMappedFile.CreateOrOpen("MySharedMemory", 1024)) { // 创建访问器 using (var accessor = mmf.CreateViewAccessor()) { // 写入整数数据到偏移量0的位置 accessor.Write(0, 12345); Console.WriteLine("Data written to shared memory."); } } } } ``` ```csharp // 进程B:读取共享内存中的数据 using System; using System.IO.MemoryMappedFiles; class Program { static void Main() { try { // 打开已存在的共享内存 using (var mmf = MemoryMappedFile.OpenExisting("MySharedMemory")) { using (var accessor = mmf.CreateViewAccessor()) { // 从偏移量0读取整数 int value = accessor.ReadInt32(0); Console.WriteLine($"Read data from shared memory: {value}"); } } } catch (Exception ex) { Console.WriteLine($"Error reading shared memory: {ex.Message}"); } } } ``` ### 实现原理 共享内存的实现依赖于操作系统的虚拟内存管理机制。每个进程拥有独立的虚拟地址空间,而共享内存则是将多个进程的虚拟地址映射到同一块物理内存上。这样,不同进程对各自虚拟地址的操作都会反映到同一块物理内存中,从而实现数据共享。 在 Linux 系统中,通常使用两种方式实现共享内存: - **System V 共享内存**:传统的 IPC 机制,提供 `shmget`、`shmat` 等系统调用来创建和访问共享内存段。 - **POSIX 共享内存**:更现代的方式,通过 `shm_open` 和 `mmap` 接口实现,具有更好的可移植性和易用性[^2]。 ### 同步与并发控制 由于共享内存允许多个进程同时访问同一块内存,因此必须引入同步机制来防止数据竞争。常用的同步手段包括: - **互斥锁(Mutex)** - **信号量(Semaphore)** - **事件(Event)** 在 C# 中,可以结合 `Mutex` 或 `Semaphore` 来确保多进程之间的安全访问。 #### 示例:添加互斥锁保护共享内存(C#) ```csharp using System.Threading; // 在进程A中加锁写入 Mutex mutex = new Mutex(false, "MySharedMemoryMutex"); mutex.WaitOne(); try { using (var mmf = MemoryMappedFile.OpenExisting("MySharedMemory")) using (var accessor = mmf.CreateViewAccessor()) { accessor.Write(0, 54321); } } finally { mutex.ReleaseMutex(); } ``` ### 应用场景 共享内存适用于需要高效传输大量数据的场景,例如: - 实时音视频数据传输 - 游戏引擎中的状态同步 - 高性能计算中的进程协作 - 操作系统内核模块与用户态程序的数据交互 ### 注意事项 - **命名冲突**:确保共享内存和同步对象的名称唯一,避免不同程序之间误操作。 - **资源释放**:使用完毕后应及时关闭访问器、内存映射文件及同步对象,避免资源泄漏。 - **权限控制**:在多用户系统中应设置适当的访问权限,防止未经授权的进程访问敏感数据。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值