共享内存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;
}

Linux IPC实践(9) --System V共享内存的更多相关文章

  1. Linux进程通信之System V共享内存

    前面已经介绍过了POSIX共享内存区,System V共享内存区在概念上类似POSIX共享内存区,POSIX共享内存区的使用是调用shm_open创建共享内存区后调用mmap进行内存区的映射,而Sys ...

  2. linux网络编程之system v共享内存

    接着上次的共享内存继续学习,这次主要是学习system v共享内存的使用,下面继续: 跟消息队列一样,共享内存也是有自己的数据结构的,system v共享内存也是随内核持续的,也就是说当最后一个访问内 ...

  3. Linux IPC实践(13) --System V IPC综合实践

    实践:实现一个先进先出的共享内存shmfifo 使用消息队列即可实现消息的先进先出(FIFO), 但是使用共享内存实现消息的先进先出则更加快速; 我们首先完成C语言版本的shmfifo(基于过程调用) ...

  4. Linux IPC实践(11) --System V信号量(1)

    信号量API #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget ...

  5. Linux IPC实践(6) --System V消息队列(3)

    消息队列综合案例 消息队列实现回射客户/服务器   server进程接收时, 指定msgtyp为0, 从队首不断接收消息 server进程发送时, 将mtype指定为接收到的client进程的pid ...

  6. Linux IPC实践(12) --System V信号量(2)

    实践1:信号量实现进程互斥 父子进程执行流程如下: 父进程 子进程 P P O(print) X(print) sleep sleep O(print) X(print) V V sleep slee ...

  7. Linux IPC实践(4) --System V消息队列(1)

    消息队列概述 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法(仅局限于本机); 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值. 消息队列也有管道一样的不足:  ...

  8. Linux IPC实践(5) --System V消息队列(2)

    消息发送/接收API msgsnd函数 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 参数 msgid: 由ms ...

  9. 阐述linux IPC(五岁以下儿童):system V共享内存

    [版权声明:尊重原创.转载请保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章学习交流,不用于商业用途]         system V共享内存和posix ...

随机推荐

  1. python常用执行方式&变量&input函数

    linux系统中执行py文件方式:  ./a.py 需要执行权限 chmod -R 777(最大权限) 常用执行方式: 1. ./a.py2. python a.py 文件内部头加上 #!/usr/b ...

  2. Vue国际化处理 vue-i18n 以及项目自动切换中英文

    1. 环境搭建 命令进入项目目录,执行以下命令安装vue 国际化插件vue-i18n npm install vue-i18n --save 2. 项目增加国际化翻译文件 在项目的src下添加lang ...

  3. springMVC源码--Controller控制器

    springMVC给我们提供Controller控制器,用来实现我们的逻辑处理,在Controller接口中定义的方法也是比较简单的,如下: Controller接口及实现类:

  4. zookeeper基本原理及适用场景 转:http://blog.chinaunix.net/uid-26748613-id-4536290.html

    1.1 zookeeper简介 Zookeeper 是 Hadoop 生态系统中的协同实现,是Hadoop集群管理的一个必不可少的模块,它主要来控制集群中的数据,如它管理Hadoop集群中的NameN ...

  5. Android适配难题全面总结

    支持多种屏幕 Android 可在各种具有不同屏幕尺寸和密度的设备上运行.对于 应用,Android 系统在不同设备中提供一致的开发环境, 可以处理大多数工作,将每个应用的用户界面调整为适应其显示的 ...

  6. 让sublime总是在新选项卡打开新文件

    sublime的一个默认设置让人很不爽,比如现在选项卡里面已经打开了一个文件A,当你从左边side bar里面点击一个新文件B时,如果你不是快速的双击,且A没有处于编辑未保存状态,那么B就会覆盖A的选 ...

  7. Spark技术内幕:Shuffle的性能调优

    通过上面的架构和源码实现的分析,不难得出Shuffle是Spark Core比较复杂的模块的结论.它也是非常影响性能的操作之一.因此,在这里整理了会影响Shuffle性能的各项配置.尽管大部分的配置项 ...

  8. Android简易实战教程--第三十话《撕衣美女》

    此篇邪恶一些,给单身屌丝发点"福利",通过图片的绘制,给美女脱掉衣服. 原理:图片覆盖图片,通过画笔对顶端的图片做一些特效处理,即手指触摸的地方,设置为透明.即可显示最底部的美女图 ...

  9. [LaTex]插图

    1.不错的Latex参考网站 http://www.ctex.org/documents/latex/graphics/node120.html http://www.ctex.org/documen ...

  10. UNIX网络编程——揭开网络编程常见API的面纱【上】

    Linux网络编程API函数初步剖析 今天我们来分析一下前几篇博文中提到的网络编程中几个核心的API,探究一下当我们调用每个API时,内核中具体做了哪些准备和初始化工作. 1.socket(famil ...