Linux IPC实践(9) --System V共享内存

简介: 共享内存API#include #include int shmget(key_t key, size_t size, int shmflg);void *shmat(int...

共享内存API

#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
//System V 共享内存基本数据结构
struct shmid_ds
{
    struct ipc_perm shm_perm;    /* Ownership and permissions: System V IPC所共有的数据结构 */
    size_t          shm_segsz;   /* Size of segment (bytes): 共享内存段的大小 */
    time_t          shm_atime;   /* Last attach time */
    time_t          shm_dtime;   /* Last detach time */
    time_t          shm_ctime;   /* Last change time */
    pid_t           shm_cpid;    /* PID of creator */
    pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */
    shmatt_t        shm_nattch;  /* No. of current attaches */
    ...
};

shmget

int shmget(key_t key, size_t size, int shmflg);

   创建共享内存,并将该内存的内容初始化为0

   打开一个已经存在共享内存, 如果打开时不知道共享内存的大小, 可以将size指定为0, shmflg可以指定为0(按照默认的权限打开);    

参数:

   key:这个共享内存段名字;

   size:共享内存大小(bytes);

   shmflg:用法类似msgget中的msgflg参数;

返回值:

   成功返回一个非负整数,即该共享内存段的标识码;失败返回-1

/**示例: 创建并打开一个共享内存 **/
int main(int argc,char **argv)
{
    const int SHM_SIZE = 1024;
    int shmid = shmget(0x1234, SHM_SIZE, 0666|IPC_CREAT);
    if (shmid == -1)
        err_exit("shmget error");
    cout << "share memory get success" << endl;
}

shmat

void *shmat(int shmid, const void *shmaddr, int shmflg);

   连接到本进程地址空间, 成功连接之后, 对该内存的操作就与malloc来的一块内存非常类似了, 而且如果这块内存中有数据, 则就可以直接将其中的数据取出来!!

参数:

   shmaddr:指定连接的地址(推荐使用NULL)

   shmflg:一般指定为0, 表示可读,可写; 而它的另外两个可能取值是SHM_RND和SHM_RDONLY(见下)

返回值:

   成功返回一个指针,指向共享内存起始地址;失败返回(void *) -1


shmaddr与shmflg组合说明

shmaddr为NULL

Linux内核自动为进程连接到进程的内存(推荐使用)

shmaddr不为NULL且shmflg无SHM_RND标记

以shmaddr为连接地址

shmaddr不为NULL且shmflg设置了SHM_RND标记

连接的地址会自动向下调整为SHMLBA的整数倍;

公式:shmaddr - (shmaddr % SHMLBA)

SHMLBA为内存页面的大小(4K)

shmflg=SHM_RDONLY

只读共享内存, 不然的话就是可读,可写的, 注意: 此处没有可读,可写这个概念

 

shmdt

int shmdt(const void *shmaddr);

参数:

   shmaddr: 由shmat所返回的指针

注意:将共享内存段与当前进程脱离不等于删除共享内存段

/** 示例: 将数据写入/读出共享内存
程序write: 将数据写入共享内存
程序read: 将数据读出共享内存(当然, 可以读取N多次)
**/
//write程序
struct Student
{
    char name[26];
    int age;
};
int main(int argc,char **argv)
{
    int shmid = shmget(0x1234, sizeof(Student), 0666|IPC_CREAT);
    if (shmid == -1)
        err_exit("shmget error");

    // 以可读, 可写的方式连接该共享内存
    Student *p = (Student *)shmat(shmid, NULL, 0);
    if (p == (void *)-1)
        err_exit("shmat error");
    strcpy(p->name, "xiaofang");
    p->age = 22;
    shmdt(p);
}
//read程序
int main(int argc,char **argv)
{
    int shmid = shmget(0x1234, 0, 0);
    if (shmid == -1)
        err_exit("shmget error");

    // 以只读方式连接该共享内存
    Student *p = (Student *)shmat(shmid, NULL, 0);
    if (p == (void *)-1)
        err_exit("shmat error");

    // 直接将其中的内容打印输出
    cout << "name: " << p->name << ", age: " << p->age << endl;
    shmdt(p);
}

shmctl

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

设置/获取共享内存属性

参数:

   cmd:将要采取的动作(三个取值见下)

   buf:指向一个保存着共享内存的模式状态和访问权限的数据结构

System V共享内存小结:

   1.共享内存被别的程序占用,则删除该共享内存时,不会马上删除(引用计数计数);

   2.此时会出现一个现象:该共享内存的key变为0x00000000,变为私有;

   3.此时还可以读,但必须还有办法获取该共享内存的ID(shmid),因为此时试图通过该共享内存的key获取该共享内存,是白费的!

/** 示例: 删除共享内存 **/
int main(int argc,char *argv[])
{
    int shmid = shmget(0x1234, 0, 0);
    if (shmid == -1)
        err_exit("shmget error");

    if (shmctl(shmid, IPC_RMID, NULL) == -1)
        err_exit("shmctl IPC_RMID error");
    cout << "share memory remove success" << endl;
}

目录
相关文章
|
6月前
|
传感器 数据采集 监控
Python生成器与迭代器:从内存优化到协程调度的深度实践
简介:本文深入解析Python迭代器与生成器的原理及应用,涵盖内存优化技巧、底层协议实现、生成器通信机制及异步编程场景。通过实例讲解如何高效处理大文件、构建数据流水线,并对比不同迭代方式的性能特点,助你编写低内存、高效率的Python代码。
281 0
|
7月前
|
SQL 缓存 安全
深度理解 Java 内存模型:从并发基石到实践应用
本文深入解析 Java 内存模型(JMM),涵盖其在并发编程中的核心作用与实践应用。内容包括 JMM 解决的可见性、原子性和有序性问题,线程与内存的交互机制,volatile、synchronized 和 happens-before 等关键机制的使用,以及在单例模式、线程通信等场景中的实战案例。同时,还介绍了常见并发 Bug 的排查与解决方案,帮助开发者写出高效、线程安全的 Java 程序。
422 0
|
9月前
|
监控 Linux 应用服务中间件
Linux多节点多硬盘部署MinIO:分布式MinIO集群部署指南搭建高可用架构实践
通过以上步骤,已成功基于已有的 MinIO 服务,扩展为一个 MinIO 集群。该集群具有高可用性和容错性,适合生产环境使用。如果有任何问题,请检查日志或参考MinIO 官方文档。作者联系方式vx:2743642415。
3186 57
|
存储 缓存 安全
Java内存模型深度解析:从理论到实践####
【10月更文挑战第21天】 本文深入探讨了Java内存模型(JMM)的核心概念与底层机制,通过剖析其设计原理、内存可见性问题及其解决方案,结合具体代码示例,帮助读者构建对JMM的全面理解。不同于传统的摘要概述,我们将直接以故事化手法引入,让读者在轻松的情境中领略JMM的精髓。 ####
192 6
|
6月前
|
边缘计算 算法 Java
Java 绿色计算与性能优化:从内存管理到能耗降低的全方位优化策略与实践技巧
本文探讨了Java绿色计算与性能优化的技术方案和应用实例。文章从JVM调优(包括垃圾回收器选择、内存管理和并发优化)、代码优化(数据结构选择、对象创建和I/O操作优化)等方面提出优化策略,并结合电商平台、社交平台和智能工厂的实际案例,展示了通过Java新特性提升性能、降低能耗的显著效果。最终指出,综合运用这些优化方法不仅能提高系统性能,还能实现绿色计算目标,为企业节省成本并符合环保要求。
248 0
|
消息中间件 Linux
Linux中的System V通信标准--共享内存、消息队列以及信号量
希望本文能帮助您更好地理解和应用System V IPC机制,构建高效的Linux应用程序。
477 48
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
901 20
|
Linux
【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解
System V信号量的概念及其在Linux中的使用,包括 `semget()`、`semctl()`和 `semop()`函数的具体使用方法。通过实际代码示例,演示了如何创建、初始化和使用信号量进行进程间同步。掌握这些知识,可以有效解决多进程编程中的同步问题,提高程序的可靠性和稳定性。
793 19
|
缓存 监控 网络协议
Linux操作系统的内核优化与实践####
本文旨在探讨Linux操作系统内核的优化策略与实际应用案例,深入分析内核参数调优、编译选项配置及实时性能监控的方法。通过具体实例讲解如何根据不同应用场景调整内核设置,以提升系统性能和稳定性,为系统管理员和技术爱好者提供实用的优化指南。 ####
|
监控 算法 Linux
Linux内核锁机制深度剖析与实践优化####
本文作为一篇技术性文章,深入探讨了Linux操作系统内核中锁机制的工作原理、类型及其在并发控制中的应用,旨在为开发者提供关于如何有效利用这些工具来提升系统性能和稳定性的见解。不同于常规摘要的概述性质,本文将直接通过具体案例分析,展示在不同场景下选择合适的锁策略对于解决竞争条件、死锁问题的重要性,以及如何根据实际需求调整锁的粒度以达到最佳效果,为读者呈现一份实用性强的实践指南。 ####