Linux共享内存实践(1)

共享内存基本概念

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据(如图)。

共享内存 VS. 其他IPC形式

用管道/消息队列传递数据

用共享内存传递数据

(内核为每个IPC对象维护一个数据结构)

共享内存生成之后,传递数据并不需要再走Linux内核,共享内存允许两个或多个进程共享一个给定的存储区域,数据并不需要在多个进程之间进行复制,因此,共享内存的传输速度更快!!

System V共享内存数据结构与基本API

//基本数据结构
struct shmid_ds
{
    struct ipc_perm shm_perm;    /* Ownership and permissions */
    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 */
    ...
};

共享内存函数 

#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);

shmget函数

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

原型:

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

参数:

key:这个共享内存段名字

size:共享内存大小

shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的

返回值:

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

//实验1:打开已经存在的共享内存
int main()
{
  // int shmget(key_t key, size_t size, int shmflg);
  //打开已经存在的共享内存
    int shmid = shmget(0x225,1024,0666);
    if (shmid == -1)
    {
        if (errno == ENOENT)
        {
            cout << "ENOENT = " << errno << endl;
        }
        err_exit("shmget error");
    }
    return 0;
}

//实验2:共享内存如若存在,则直接使用;若不存在,则创建. [IPC_CREAT选项作用]
int main()
{
    // int shmget(key_t key, size_t size, int shmflg);
    int shmid = shmget(0x225,1024,0666|IPC_CREAT);
    if (shmid == -1)
    {
        if (errno == ENOENT)
        {
            cout << "ENOENT = " << errno << endl;
        }
        err_exit("shmget error");
    }
    else
    {
        cout << "shmid = " << shmid << endl;
    }
    return 0;
}

//实验3:共享内存如果没有,则创建;如果存在,则返回错误. [IPC_CREAT|IPC_EXCL组合作用]
int main()
{
    // int shmget(key_t key, size_t size, int shmflg);
    int shmid = shmget(0x225,1024,0666|IPC_CREAT|IPC_EXCL);
    if (shmid == -1)
    {
        if (errno == ENOENT)
        {
            cout << "ENOENT = " << errno << endl;
        }
        else if (errno == EEXIST)
        {
            cout << "File is exits... EEXIST = " << errno << endl;
        }
        err_exit("shmget error");
    }
    else
    {
        cout << "shmid = " << shmid << endl;
    }
    return 0;
}

shmat函数

功能:将共享内存段连接到进程地址空间

原型:

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

参数:

shmid: 共享内存标识

shmaddr:指定连接的地址

shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY

返回值:

成功返回一个指针,指向共享内存第一个节;失败返回-1

Shmaddr与shmflg组合说明

shmaddr为NULL,Linux内和将自动为进程连接到该内存(推荐使用)

shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。

shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA)

shmflg=SHM_RDONLY,表示连接操作用来只读共享内存

//示例1
int main()
{
    // int shmget(key_t key, size_t size, int shmflg);
    //获取或者打开共享内存
    int shmid = shmget(0x1576422, sizeof(Student), 0666 | IPC_CREAT);
    if (shmid == -1)
    {
        err_exit("shmget error");
    }

    //将ID为shmid的共享内存连接到该进程
    Student *pStudent = static_cast<Student *>(shmat(shmid, NULL, 0));
    //向内存中写入数据
    Student studentA = {"xiaofang",2012};
    memcpy(pStudent,&studentA,sizeof(Student));

    cout << pStudent ->name << " " << pStudent ->number << endl;

    //亦可获取该内存内容(其实跟本地内存没有什么区别)
    Student *pNewStudent = pStudent;
    cout << pNewStudent -> name << " " << pNewStudent -> number << endl;

    return 0;
}

//示例2:将共享内存当成数组
int main()
{
    // int shmget(key_t key, size_t size, int shmflg);
    //获取或者打开共享内存
    int shmid = shmget(0x15764221, 1024 * sizeof(int), 0666 | IPC_CREAT);
    if (shmid == -1)
    {
        err_exit("shmget error");
    }

    //将ID为shmid的共享内存连接到该进程
    int *pArray = static_cast<int *>(shmat(shmid, NULL, 0));
    if (pArray == (void *)-1)
    {
        err_exit("shmat error");
    }

    for (int i = 0; i != 1024; ++i)
    {
        pArray[i] = i+1;
    }

    for (int i = 0; i != 1024; ++i)
    {
        cout << pArray[i] << endl;
    }

    return 0;
}

时间: 2024-09-30 00:45:53

Linux共享内存实践(1)的相关文章

Linux共享内存实践(2)

shmdt函数 功能:将共享内存段与当前进程脱离 原型: int shmdt(const void *shmaddr); 参数: shmaddr: 由shmat所返回的指针 返回值: 成功返回0:失败返回-1 //实践:运行程序,观察ipcs输出 int main() { //获取或者打开共享内存 int shmid = shmget(0x15764221, 1024 * sizeof(int), 0666 | IPC_CREAT); if (shmid == -1) { err_exit("s

unix/linux共享内存应用与陷阱

unix/linux共享内存应用与陷阱 (2012-06-12 14:32) 标签:  linux  内存  分类: linux应用  共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区.在/proc/sys/kernel/目录下,记录着共享内存的一些限制,如一个共享内存区的最大字节数shmmax,系统范围内最大共享内存区标识符数shmmni等,可以手工对其调整,但不推荐这样做.一.应用共享内存的使用,主要有以下几个API:ftok().shmget().shmat().shmdt(

linux 共享内存实现

说起共享内存,一般来说会让人想起下面一些方法:1.多线程.线程之间的内存都是共享的.更确切的说,属于同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享:2.父子进程间的内存共享.父进程以MAP_SHARED|MAP_ANONYMOUS选项mmap一块匿名内存,fork之后,其子孙进程之间就能共享这块内存.这种共享内存由于受到进程父子关系的限制,一般较少使用:3.mmap文件.多个进程mmap到同一个文件,实际上就是大家在共享文件page cache中的内存.不过文件牵涉到

一张图深度解析Linux共享内存的内核实现

一张图深度解析Linux共享内存的内核实现 Sailor_forever  sailing_9806#163.com http://blog.csdn.net/sailor_8318/article/details/39484747 (本原创文章发表于Sailor_forever 的个人blog,未经本人许可,不得用于商业用途.任何个人.媒体.其他网站不得私自抄袭:网络媒体转载请注明出处,增加原文链接,否则属于侵权行为.如有任何问题,请留言或者发邮件给sailing_9806#163.com)

【转】Linux共享内存编程实例

原文地址:http://blog.csdn.net/pcliuguangtao/article/details/6526119 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 6

Linux共享内存使用常见陷阱与分析 - 51CTO.COM http://os.51cto.com/art/201311/418977_all.htmIPC---共享内存

共享内存就是允许两个或多个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据时,不需要在客户进程和服务器进程之间幅值,因此是最快的一种IPC.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 注意:共享内存并未提供同步机制,也就是说,

linux 共享内存shm_open实现进程间大数据交互

linux 共享内存shm_open实现进程间大数据交互 read.c #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <sys/mman.h> #include <string.h> #include <errno.h> #include <unistd.h> /* int

Linux共享内存(一)

inux系统编程我一直看 <GNU/LINUX编程指南>,只是讲的太简单了,通常是书和网络上的资料结合着来掌握才比较全面 .在掌握了书上的内容后,再来都其他资料 . 原文链接 http://www.cnblogs.com/skyme/archive/2011/01/04/1925404.html 共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区.在/proc/sys/kernel/目录下,记录着共享内存的一些限制,如一个共享内存区的最大字节数shmmax,系统范围内最大共享内存区

Linux 共享内存使用

什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 特别提醒:共享内存并未提供同步机制,也就是说,在第一个进程结束对共