精华内容
下载资源
问答
  • 自己整理的Linux5个共享内存头文件, 通过编写共享内存实验,进一步了解使用共享内存的具体步骤,同时加深对共享内存的理解。在本实验中,采用信号量作为同步机制完善两个进程(“生产者”和“消费者”)之间的通信。
  • Linux共享内存

    2018-04-30 15:56:58
    Linux共享内存1.什么是共享内存在前面讲虚拟内存机制时,有讲到Linux的内存映射机制:初始化虚拟内存区域时,会把虚拟内存和磁盘文件对象对应起来。由于内存映射机制,一个磁盘文件对象可被多个进程共享访问,也可被...

    Linux共享内存

    1.什么是共享内存
    在前面讲虚拟内存机制时,有讲到Linux的内存映射机制
    初始化虚拟内存区域时,会把虚拟内存和磁盘文件对象对应起来。
    由于内存映射机制,一个磁盘文件对象可被多个进程共享访问,也可被多个进程私有访问。
    当共享访问时,一个进程的对该对象的修改会显示到其他进程。
    当私有访问时,修改时会产生保护故障,内核会拷贝这个私有对象,修改的是这个新对象,其他进程指向的是原来的对象。
    所以,共享内存是指不同进程访问同一个逻辑内存

    2.共享内存的使用
    Linux提供了一组共享内存API,声明在头文件sys/shm.h中。
    1)shmget函数:新建共享内存
    int shmget(key_t key,size_t size,int shmflg);
    key:共享内存键值,可以理解为共享内存的唯一性标记。
    size:共享内存大小
    shmflag:创建进程和其他进程的读写权限标识。
    返回值:相应的共享内存标识符,失败返回-1

    2)shmat函数:连接共享内存到当前进程的地址空间
    void *shmat(int shm_id,const void *shm_addr,int shmflg);
    shm_id:共享内存标识符
    shm_addr:指定共享内存连接到当前进程的地址,通常为0,表示由系统来选择。
    shmflg:通常为0
    返回值:指向共享内存第一个字节的指针,失败返回-1

    3)shmdt函数:当前进程分离共享内存
    int shmdt(const void *shmaddr);

    4)shmctl函数
    和信号量的semctl函数类似,控制共享内存
    int shmctl(int shm_id,int command,struct shmid_ds *buf);
    shm_id:共享内存标识符
    command: 有三个值
          IPC_STAT:获取共享内存的状态,把共享内存的shmid_ds结构复制到buf中。
          IPC_SET:设置共享内存的状态,把buf复制到共享内存的shmid_ds结构。
          IPC_RMID:删除共享内存
    buf:共享内存管理结构体。具体结构可参考定义。

    3.共享内存需要注意的问题
    共享内存没有同步机制,当多个进程同时向共享内存读写数据时,我们需要使用互斥锁,读写锁,信号量,条件变量等来确保数据的一致性。

    4.共享内存使用示例

    我们编写了两个程序shmread.c,shmwrite.c分别对共享内存读和写。
    需要做到可写,然后可读,然后可写,然后可读,循环下去,直到写入的是"end",结束写读进程。
    我们使用了前面讲的信号量来处理读写同步的问题。
    示例代码如下:

    shm_data.h

    复制代码
    #pragma once                                                                    
    #define TEXT_SZ 2048
    struct shared_use_st
    {
            char text[TEXT_SZ];
    };
    复制代码

    shmread.c

    复制代码
    #include<stdio.h>
    #include<stdlib.h>
    #include<sys/shm.h>
    #include<sys/sem.h>
    #include"shmdata.h"
    union semun  
    {  
        int val;  
        struct semid_ds *buf;  
        unsigned short *arry;  
    }; 
    int sem_id;
    int set_semvalue()  
    {  
        //用于初始化信号量,在使用信号量前必须这样做  
        union semun sem_union;  
      
        sem_union.val = 1;  
        if(semctl(sem_id, 0, SETVAL, sem_union) == -1)  
            return 0;  
        return 1;  
    }  
      
    void del_semvalue()  
    {  
        //删除信号量  
        union semun sem_union;  
      
        if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1)  
            fprintf(stderr, "Failed to delete semaphore\n");  
    }  
    int semaphore_p()
    {
        struct sembuf sem_b;  
        sem_b.sem_num = 0;  
        sem_b.sem_op = -1;//P()  
        sem_b.sem_flg = SEM_UNDO;  
        if(semop(sem_id, &sem_b, 1) == -1)  
        {  
            fprintf(stderr, "semaphore_p failed\n");  
            return 0;  
        }  
        return 1;   
    }
    int semaphore_v()
    {
        struct sembuf sem_b;  
        sem_b.sem_num = 0;  
        sem_b.sem_op = 1;//V()  
        sem_b.sem_flg = SEM_UNDO;  
        if(semop(sem_id, &sem_b, 1) == -1)  
        {  
            fprintf(stderr, "semaphore_v failed\n");  
            return 0;  
        }  
        return 1;  
    }
    int main()
    {
        void *shm=NULL;
        struct shared_use_st *shared;
        int shmid;//共享内存标识符
        //创建共享内存
        shmid = shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
        if(shmid==-1)
        {
            fprintf(stderr,"shmget failed\n");
            exit(EXIT_FAILURE);
        }
        //将共享内存连接到当前进程的地址空间
        shm = shmat(shmid,0,0);
        if(shm==(void*)-1)
        {
            fprintf(stderr,"shmat failed\n");
            exit(EXIT_FAILURE);
        }
        printf("memory attached at %x\n",(int)shm);
        //设置共享内存
        shared = (struct shared_use_st*)shm;
        
        //新建信号量
        sem_id = semget((key_t)1234,1,0666|IPC_CREAT);
    
        //信号量初始化
        if(!set_semvalue())
        {
            fprintf(stderr,"init failed.\n");
            exit(EXIT_FAILURE);
        }
        
        while(1)
        {
            if(!semaphore_p())
                exit(EXIT_FAILURE);
            fflush(stdout);
            printf("you wrote:%s",shared->text);
            if(!semaphore_v())
                exit(EXIT_FAILURE);
            if(strncmp(shared->text,"end",3)==0)
                break;
            sleep(1);
        }
        
         //删除信号量
        del_semvalue();
    
        //把共享内存从当前进程中分离
        if(shmdt(shm)==-1)
        {
            fprintf(stderr,"shmdt failed\n");
            exit(EXIT_FAILURE);
        }
        //删除共享内存
        if(shmctl(shmid,IPC_RMID,0)==-1)
        {
            fprintf(stderr,"shmctl(IPC_RMID) failed");
            exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
    }
    复制代码

    shmwrite.c

    复制代码
    #include<stdio.h>
    #include<stdlib.h>
    #include<sys/shm.h>
    #include<sys/sem.h>
    #include<string.h>
    #include"shmdata.h"
    int sem_id;
    int semaphore_p()
    {
        //对信号量做减1操作,即等待P(sv)  
        struct sembuf sem_b;  
        sem_b.sem_num = 0;  
        sem_b.sem_op = -1;//P()  
        sem_b.sem_flg = SEM_UNDO;  
        if(semop(sem_id, &sem_b, 1) == -1)  
        {  
            fprintf(stderr, "semaphore_p failed\n");  
            return 0;  
        }  
        return 1;  
    }  
    int semaphore_v()  
    {  
        //这是一个释放操作,它使信号量变为可用,即发送信号V(sv)  
        struct sembuf sem_b;  
        sem_b.sem_num = 0;  
        sem_b.sem_op = 1;//V()  
        sem_b.sem_flg = SEM_UNDO;  
        if(semop(sem_id, &sem_b, 1) == -1)  
        {  
            fprintf(stderr, "semaphore_v failed\n");  
            return 0;  
        }  
        return 1;  
    }  
    int main()
    {
        sem_id = semget((key_t)1234,1,0666|IPC_CREAT);
        
        void *shm = NULL;
        struct shared_use_st *shared = NULL;
        char buffer[200];
        int shmid;
    
        //创建共享内存
        shmid = shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
        if(shm==-1)
        {
            fprintf(stderr,"shmget failed\n");
            exit(EXIT_FAILURE);
        }
        //将共享内存连接到当前进程的地址空间
        shm = shmat(shmid,(void*)0,0);
        if(shm == (void*)-1)
        {
            fprintf(stderr,"shmat failed\n");
            exit(EXIT_FAILURE);
        }
        printf("memory attached at %x\n",(int)shm);
        //设置共享内存
        shared = (struct shared_use_st*)shm;
        while(1)
        {
            if(!semaphore_p())
                exit(EXIT_FAILURE);
            //向共享内存中写入数据
            fflush(stdout);
            printf("Enter some text...\n");
            fgets(buffer,200,stdin);
            strncpy(shared->text,buffer,TEXT_SZ);
            if(!semaphore_v())
                exit(EXIT_FAILURE);
            if(strncmp(shared->text,"end",3)==0)
                break;
            sleep(1);
        }
        //把共享内存从当前进程中分离
        if(shmdt(shm)==-1)
        {
            fprintf(stderr,"shmdt failed\n");
            exit(EXIT_FAILURE);
        }
        sleep(2);
        exit(EXIT_SUCCESS);
    }
    复制代码

    输出结果:

    5.共享内存的优缺点
    1)进程间通信方便,快速。
    2)没有提供同步机制,我们需要使用互斥锁,读写锁,信号量,条件变量等来确保数据的一致性。

    展开全文
  • 一、Linux进程通信Linux系统下进程通信的方式有很多:管道(pipe)命名管道(FIFO)内存映射(mapped memeory)消息队列(message queue)共享内存(shared memory)信号量(semaphore)信号(signal)套接字(Socket)共享内存允许...

    一、Linux进程通信

    Linux系统下进程通信的方式有很多:

    管道(pipe)

    命名管道(FIFO)

    内存映射(mapped memeory)

    消息队列(message queue)

    共享内存(shared memory)

    信号量(semaphore)

    信号(signal)

    套接字(Socket)

    共享内存允许两个或更多进程访问同一块内存。内存共享是使用的比较简单方便的一种了,简单的一些数据通信和文件共享,用内存共享非常方便。说起内存共享就得提一提多线程、多进程间的内存共享。线程之间的内存都是共享的。严格的说,同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享;父子进程间的内存共享。父进程以MAP_SHARED|MAP_ANONYMOUS选项mmap一块匿名内存,fork之后,其子孙进程之间就能共享这块内存。

    二、Linux共享内存使用

    Linux内存共享有几种不同的实现方式

    基于传统SYS V的共享内存;

    基于POSIX mmap文件映射实现共享内存;

    通过memfd_create()和fd跨进程共享实现共享内存;

    这里我们着重了解一下SYS V的共享内存。

    首先来了解下共享内存原理,

    e49cc147084ac688d2b02ccbd17a4724.png

    当2个或者多个进程通过页表把虚拟内存地址映射到物理后,在物理地址就有一块共同能访问到的内存,就是内存共享区。A,B进程就可以操作这块区域进行数据的交换。

    1.基本使用步骤

    生成键值

    key_t ftok(const char *path ,int id);

    创建内存共享区

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

    2.写共享数据

    #include

    #include

    #include

    #include

    #include

    #include

    #include

    int main()

    {

    key_t key = ftok(".",0x7777);

    if(key < 0)

    {

    perror("ftok failed");

    return -1;

    }

    //创建共享内存

    int shmid = shmget(key,4096,IPC_CREAT|IPC_EXCL|0666);

    if(shmid<0)

    {

    perror("shmget failed");

    }

    //映射,将共享内存挂接到进程地址空间

    char* buf = shmat(shmid,NULL,0);

    int i=0;

    memset(buf,'\0',sizeof(buf));

    strcat(buf,"第六天魔王,");

    //分离去关联

    shmdt(buf);

    //等待输入退出

    while(getchar() == '\0');

    //删除共享内存

    shmctl(shmid,IPC_RMID,NULL);

    return 0;

    }

    3.读共享数据

    #include

    #include

    #include

    #include

    #include

    #include

    int main()

    {

    key_t key = ftok(".",0x7777);

    if(key < 0)

    {

    perror("ftok failed");

    return 1;

    }

    //创建共享内存

    int shmid = shmget(key,4096,IPC_CREAT);

    if(shmid<0)

    {

    perror("shmget failed");

    return 2;

    }

    //映射共享内存区

    char* buf = shmat(shmid,NULL,0);

    //读取共享数据

    printf("read shm data: %s\n",buf);

    //分离去关联

    shmdt(buf);

    return 0;

    }

    编译文件:gcc -o xxx xxx.c

    先执行写,把数据写到共享区域

    c11653fcf0e9438dcb8acb4033f8c1e9.png

    使用命令ipcs -m即可读出系统共享内存相关信息。执行读共享内存。

    50d610923055717b0cb98e43a448c97c.png

    我们可以看到在主键0x7701a32创建了4096字节的共享区域,权限是666,当有进程访问时连接数就会变化。如果共享内存区域已存在,再次去创建就会报错,如果需要删除共享区域,则要执行函数

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

    当然也可以用命令去手动删除:ipcrm -M 0x7701a32,这样就把上面创建的共享内存区域删除了。

    1.键值key可以ftok生成,也可以指定固定值

    2.如果共享区域被删除了,再去访问读数据会造成程序崩溃

    3.内存共享一般要配合信号量进行数据同步

    三、Qt共享内存SharedMemory使用

    Qt的内存共享操作封装在SharedMemory类里,使用相比Linux原生内存共享也更简单一点。

    1.SharedMemory类介绍

    //默认构造函数

    QSharedMemory(QObject *parent = Q_NULLPTR);

    //构造函数,携带key参数

    QSharedMemory(const QString &key, QObject *parent = Q_NULLPTR);

    //析构

    ~QSharedMemory();

    //设置key

    void setKey(const QString &key);

    //返回key

    QString key() const;

    //设置平台特点key

    void setNativeKey(const QString &key);

    //返回key

    QString nativeKey() const;

    //创建共享内存,指定大小和读写模式

    bool create(int size, AccessMode mode = ReadWrite);

    //返回共享内存大小

    int size() const;

    //关联共享内存

    bool attach(AccessMode mode = ReadWrite);

    //判断是否已关联共享内存

    bool isAttached() const;

    //分离共享内存

    bool detach();

    //返回共享内存数据

    void *data();

    //返回const指针共享内存const数据

    const void* constData() const;

    //返回const指针共享内存数据

    const void *data() const;

    #ifndef QT_NO_SYSTEMSEMAPHORE

    //锁住共享内存

    bool lock();

    //解锁共享内存

    bool unlock();

    #endif

    //返回共享内存错误

    SharedMemoryError error() const;

    //返回共享内存错误QString类型

    QString errorString() const;

    这里使用内置的lock进行数据同步,当然也可以使用信号量进行同步。

    并且Qt会在最后一个进程或线程detach()之后直接销毁QSharedMemory。

    下面展示一个通过内存共享一个进行把图片写道内存区域,另外一个进程读图片并显示出来。

    2.写共享数据

    void ShmWriter::WriteToShareMemory()

    {

    //准备图片数据

    QImage image;

    if(!image.load(":/img/puzzle.jpg"))

    {

    qDebug()<

    return;

    }

    QBuffer buff;

    buff.open(QBuffer::WriteOnly);

    QDataStream out(&buff);

    out<

    //创建共享内存对象并设置key为"ImageShm"

    mShmWriter = new QSharedMemory("ImageShm",this);

    if(mShmWriter->isAttached())

    {

    //还在连接状态则进行分离

    mShmWriter->detach();

    }

    //创建共享内存

    if(!mShmWriter->create(buff.size()))

    {

    qDebug()<errorString();

    return;

    }

    //锁住共享区域

    mShmWriter->lock();

    //拷贝数据到共享内存

    char *shmAddr = (char*)mShmWriter->data();

    const QByteArray arry(buff.data());

    const char *i_data = arry.data();

    memcpy(shmAddr,i_data,buff.size());

    //解锁

    mShmWriter->unlock();

    }

    3.读共享数据

    void ShmReader::readFromShareMemory()

    {

    //锁定

    mShmReader->lock();

    //关联共享内存

    if(!mShmReader->attach())

    {

    qDebug()<errorString();

    return;

    }

    // 从共享内存中读取数据

    QBuffer buffer;

    QDataStream in(&buffer);

    QImage image;

    buffer.setData( (const char*)mShmReader->constData(),mShmReader->size());

    buffer.open(QBuffer::ReadOnly);

    in>>image;

    //解锁

    mShmReader.unlock();

    //分离共享内存

    mShmReader.detach();

    //显示

    ui->label->setPixmap(QPixmap::fromImage(image));

    }

    最终读出图片数据,显示如下。

    74b995aca3bbf3cc6f586cb28c5945fe.png

    Qt的共享内存key可以在实例化的时候把key带进去,也可以使用setKey函数进行key的设置。读写端key必须保持一致。

    代码示例链接:https://download.csdn.net/download/haohaohaihuai/12566419

    作者:费码程序猿

    欢迎技术交流:QQ:255895056

    转载请注明出处,如有不当欢迎指正

    展开全文
  • Linux共享内存及共享内存API

    千次阅读 2018-01-23 16:31:45
    共享内存从服务器拷贝文件数据到客户端: 共享内存基本API: #include #include 1. int shmget(key_t key,size_t size,int shmflg); 功能:用来创建共享内存 key:是这个共享内存段的名字 size:...

    共享内存区是最快的IPC(进程间通信)形式。

    用共享内存从服务器拷贝文件数据到客户端:


    共享内存基本API:

    #include<sys/ipc.h>

    #include<sys/shm.h>

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

    功能:用来创建共享内存

    key:是这个共享内存段的名字
    size:共享内存的大小
    shmflg:相当于权限位(如0666)
    返回值是共享内存段的标识码shmid,
    例如:shmid = shmget(0x1111, 128, 0666);
        //创建共享内存 , 相当于打开打开文件 
     //若共享内存存在 则使用   fopen()
     //若共享内存 不存在 则报错 -1

    shmid = shmget(0x1111, 128, 0666 | IPC_CREAT);
         //创建共享内存 , 相当于打开打开文件 
       //若共享内存存在 则使用   fopen()
      //若共享内存 不存在 则创建 


    shmid = shmget(0x1111, 128, 0666 | IPC_CREAT | IPC_EXCL);
     //创建共享内存 , 相当于打开文件 
    //若共享内存存在 则报错
    //若共享内存 不存在 则创建 
    //作用 IPC_EXCL判断存在不存在的标志  避免已经存在的文件 被覆盖

    2.  void *shmat(int shmid, const void *shmaddr, int shmflg);0xaa11

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

    shmaddr:指定连接的地址,因为内存地址是段页式管理,所以有可能传入的地址并不就是那一页的开头位置,所以传入一个地址,传出的仍然是一个地址,传出的是具体开始存储的地址。所以我们通常传入NULL,让编译器直接分配个合适的位置给我们。

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

    例: void *p = shmat(shmid, NULL, 0);

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


    3, int shmdt(const void *shmaddr);

    功能:将共享内存段与当前进程脱离,但并不等于删除共享内存段


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

    功能:用于控制共享内存

    cmd:将要采取的动作

    1,IPC_STAT  把shmid_ds结构中的数据设置为共享内存的当前关联值

    2,IPC_SET    在进程有足够权限的前提下,把共享内存的当前关联值设置为shmid_ds数据结构中给出的值

    3,IPC_RMID  删除共享内存段

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

       例: shmctl(shmid, IPC_RMID, NULL);

       //删除共享内存

    若想要把旧的共享内存里面的内容保存下来,则传入一个地址,用来完成保存的功能


    为什么链接共享内存时要设计shmid,创建时要传入key:

    共享内存私有:





    Linux内核通过引用计数技术来管理共享内存生命周期







    展开全文
  • linux 共享内存

    2020-09-16 00:37:27
    概述 注意事项 软件包的来源 安装软件包需要注意的问题 编译程序 编译和安装 更多的资料 安装到系统中的文件
  • Linux 共享内存

    2012-12-24 17:17:22
     Linux共享内存有mmap和System V两种方式  1.mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read()...

        Linux下共享内存有mmap和System V两种方式

        1.mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。由此看来mmap并不纯粹是为实现共享内存而设计的

       2.System V 共享内存是通过映射特殊文件系统 shm 中的文件实现进程间的共享内存通信,即把所有共享数据放在共享内存区域, 任何想要访问该数据的进程都必须在本进程的地址空间新增一块内存区域,用来映射存放共享数据的物理内存页面。

       两者从应用上来看,区别不大,一个是操作普通文件,一个是操作交换分区上的 shm 文件系统

     

    1. mmap方式

       写进程:

    #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>
    
    #define SHMNAME "shm_ram"
    #define OPEN_FLAG O_RDWR|O_CREAT
    #define OPEN_MODE 00777
    #define FILE_SIZE 4096*4
    
    int main(int argc,char **argv)
    {
    	int ret = -1;
    	int fd = -1;
    
    	void* add_w = NULL;
    
    	//创建或者打开一个共享内存
    	fd = shm_open(SHMNAME, OPEN_FLAG, OPEN_MODE);
    	if(-1 == (ret = fd))
    	{
    		perror("shm  failed: ");
    		return ret;;
    	}
    	
    	
    	//调整确定文件共享内存的空间
    	ret = ftruncate(fd, FILE_SIZE);
    	if(-1 == ret)
    	{
    		perror("ftruncate");
    		return ret;;
    	}
    	
    	// 映射目标文件的存储区
    	add_w = mmap(NULL, FILE_SIZE, PROT_WRITE, MAP_SHARED, fd, SEEK_SET);
    	if(NULL == add_w)
    	{
    		perror("mmap");
    		return ret;;
    	}
    
    
    	// memcpy 内存共享 写入内容
    	memcpy(add_w, "howaylee", sizeof("howaylee"));
    
    	// 取消映射
    	ret = munmap(add_w, FILE_SIZE);
    	if(-1 == ret)
    	{
    		perror("munmap add_w faile: ");
    		return ret;;
    	}
    	
    	// 删除内存共享
    	/*shm_unlink(SHMNAME);
    	if(-1 == ret)
    	{
    		perror("shm_unlink faile: ");
    		return ret;;
    	}*/
    }

     

        读进程

    int main(int argc,char **argv)
    {
    	int ret = -1;
    	int fd = -1;
    
    	char buf[4096] = {0};
    	void* add_r = NULL;
    
    	//创建或者打开一个共享内存
    	fd = shm_open(SHMNAME, OPEN_FLAG, OPEN_MODE);
    	if(-1 == (ret = fd))
    	{
    		perror("shm");
    		return ret;
    	}
    	
    		//调整确定文件共享内存的空间
    	ret = ftruncate(fd, FILE_SIZE); // 16k
    	if(-1 == ret)
    	{
    		perror("ftruncate");
    		return ret;
    	}
    	
    	// 映射目标文件的存储区
    	add_r = mmap(NULL, FILE_SIZE, PROT_READ, MAP_SHARED, fd, SEEK_SET);
    	if(NULL == add_r)
    	{
    		perror("mmap");
    		return ret;
    	}
    
    	// memcpy 内存共享 写入内容
    	memcpy(buf, add_r, sizeof(buf));
    	
    	printf("buf = %s\n", buf);
    
    	// 取消映射
    	ret = munmap(add_r, FILE_SIZE);
    	if(-1 == ret)
    	{
    		perror("munmap");
    		return ret;
    	}
    } 

     

    2. System V方式

       system V API比较简洁,只涉及到 shmget(),shmmat(),shmmdt(),shmctrl()四个函数,与信号量函数命名一致

       

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    #define MY_SHM_ID 0x00004589
    #define IPC_BUF_SIZE 1*1024*1024
    
    pthread_mutex_t mutex;
    bool WriteShmMsg(const char *szMsg)
    {
    	if(pthread_mutex_init(&mutex,NULL)!=0)
    	{
    		printf("错误:初始化锁失败\n");
    		return false;
    	}
    	
    	// 创建共享内存区
    	if((shmid=shmget(MY_SHM_ID,IPC_BUF_SIZE,0600|IPC_CREAT))<0)
    	{
    		perror("shmget");
    		return false;
    	}
    
    	void *mem;
    	
    	// 映射共享内存区
    	if((mem=shmat(shmid,0,0))==(void*)-1)
    	{
    		perror("shmat");
    		return false;
    	}
    
    	sprintf((char*)mem,"%s",szMsg); // 写入消息
    	shmdt(mem); // 取消共享内存映射
    
    	pthread_mutex_unlock(&mutex);
    	return true;
    }
    

     

       更多内容参见:

       http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html

       http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index2.html

    展开全文
  • Linux共享内存实现机制的详解 内存共享: 两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一...
  • Linux进程间通信-共享内存mmap采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而...
  • linux共享内存

    2019-08-04 01:38:06
    三种: 共享内存、消息队列、信号灯 这个IPC对象,肯定是存在于内核中。而且用户空间的文件系统中有没有IPC的文件类型?没有。 有名管道为什么能实现无亲缘关系的进程之间的通信? 是因为用户空间有管道这种文件类型...
  • Linux共享内存IPC

    2019-07-09 20:16:14
    Linux\Unix IPC进程通信实例分析(一):共享内存通信—文件映射mmap方式 https://blog.csdn.net/lzx_bupt/article/details/7658371 Linux 进程间通信(IPC)之共享内存详解与测试用例 ...
  • Linux共享内存与互斥锁

    千次阅读 2018-08-07 09:02:34
    Linux共享内存 共享内存是从系统的空闲内存池中分配,并希望访问它的每个进程都能连接它。连接的过程称为映射。映射后,每个进程都可通过访问自己的内存而访问共享内存区域,进而与其它进程进行通信。 共享内存...
  • Linux进程间通信-共享内存mmap采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而...
  • linux共享内存介绍

    2017-09-07 10:09:45
    共享内存可以通过mmap()映射普通文件 (特殊情况下还可以采用匿名映射)机制实现,也可以通过systemV共享内存机制实现。应用接口和原理很简单,内部机制复杂。为了实现更安全通信,往往还与信号灯等同步机制共同使用...
  • Linux共享内存对象二

    2019-04-19 13:09:30
    //打开创建共享内存文件 返回值:成功返回fd>0 失败返回fd<0 int shm_unlink(const char *name);//删除共享内存 int ftruncate(int fd, off_t length);//重置共享内存文件大小 void *mm...
  • 提到内存,我们会想到经常接触的三个词:虚拟内存、物理内存、共享内存。它们分别对应top输出中的VIRT、RES、SHR三列。1. 物理内存系统的物理内存被划分为许多相同大小的部分,也称作内存页。内存页的大小取决于CPU...
  • Linux 共享内存例子

    千次阅读 2016-12-13 18:35:32
    write.c文件 #include #include #include #include #include #include #include #include ...int shm_open(const char...//创建或打开一个共享内存,成功返回一个整数的文件描述符,错误返回-1。 1.name:共享内存
  • 关于Linux共享内存的实验 [一] 上文采用的“删文件”和“杀进程”的方法主要是为了快速演示实验现象,但这种做法不利于通过调试手段进一步探究其内在的逻辑。为此,在原程序的基础上,引入一个信号的处理,并通过...
  • linux 共享内存实现

    2014-04-28 00:20:00
    说起共享内存,一般来说会让人想起下面一些方法:1、多线程。线程之间的内存都是共享的。更确切的说,属于同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享;2、父子进程间的内存共享。...
  • 前面的文章提到,基于mmap映射可以实现Linux中的共享内存(shared memory)。传统的共享内存是System V形式的,可通过"/proc/sys/kernel/shmall"参数限制其占用的最大物理内存空间,像这样:echo 1024 > /proc/sys/...
  • 浅析Linux共享内存与tmpfs文件系统

    千次阅读 2018-03-30 16:44:45
    浅析Linux共享内存与tmpfs文件系统前言共享内存主要用于进程间通信,Linux有两种共享内存(Shared Memory)机制:(1) ** System V shared memory(shmget/shmat/shmdt) ** Original shared memory mechanism, still...
  • linux共享内存的设计

    2017-11-12 03:01:00
    posix的共享内存是通过用户空间挂在的tmpfs文件系统实现的,而system V的共享内存是由内核本身的tmpfs实现的,这里可以看出,二者其实是用同一种机制实现的,不同的是用户接口不同,posix旨在提供一套统一的可用接口...
  • linux共享内存设置

    千次阅读 2015-08-09 12:45:30
    最近频繁遇到共享内存的问题,这里总结一下一些设置: cat /proc/sys/kernel/shmmax cat /proc/sys/kernel/shmmni cat /proc/sys/kernel/shmall 临时修改这三个参数的值,通过echo或sysctl命令修改proc文件中的...
  • linux共享内存mmap

    2015-01-07 23:08:24
    文章来源于网络   (1)void *mmap(void *start, size_t len, intprot, int flag, int fd, off_t offset );...MAP_SHARED对映射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。 MAP_PRIVATE 对映

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,080
精华内容 1,232
关键字:

linux共享内存文件

linux 订阅