Linux 编程 共享内存

关于共享内存的操作,要用到shmget、shmat、shmctl、shmdt这几个函数,详细说明请大家查看手册

调试的时候可以使用命令ipcs,ipcs -m可以看到共享内存的情况,ipcs -s可以看到信号量的使用情况

以下是我对这几个函数的封装

#ifndef SHAREDMEMORY_H
#define SHAREDMEMORY_H

#include <sys/shm.h>

#define READ_WRITE_FLAG (S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH)

class SharedMemory
{
    public:
        SharedMemory(key_t key,size_t size,const int option);
        void* SharedMemoryMat();
        void Detach(void* sharedMemory);
        void DeleteSharedMemory();

    private:
        int shmID;
};

#endif

SharedMemory.cpp

#include "SharedMemory.h"
#include "SharedMemoryException.h"

SharedMemory::SharedMemory(key_t key,size_t size,const int option)
{
    shmID=shmget(key,size,option);
    if(shmID==-1)
        throw SharedMemoryException("Failed to get shared memory");
}

void* SharedMemory::SharedMemoryMat()
{
    //use (void*)0 to let system select the address of shared memory
    void* sharedMemory=shmat(shmID,(void*)0,0);
    if(sharedMemory==(void*)-1)
        throw SharedMemoryException("Failed in shmat");

    return sharedMemory;
}

void SharedMemory::Detach(void* sharedMemory)
{
    if(shmdt(sharedMemory)==-1)
        throw SharedMemoryException("Failed to delete shared memory");
}

void SharedMemory::DeleteSharedMemory()
{
    if(shmctl(shmID,IPC_RMID,0)==-1)
        throw SharedMemoryException("Failed to detach shared memory");
}

然后进程之间还要额外进行同步,这里使用信号量进行同步(注意进程同步的信号量与线程的是不一样的)

#ifndef SEMAPHORE_H
#define SEMAPHORE_H

#include <sys/sem.h>
#include <sys/stat.h>

union semun
{
   int              val;    /* Value for SETVAL */
   struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
   unsigned short  *array;  /* Array for GETALL, SETALL */
   struct seminfo  *__buf;  /* Buffer for IPC_INFO
                               (Linux-specific) */
};


#define READ_WRITE_FLAG (S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH)

class Semaphore
{
    public:
        Semaphore(key_t key,int option);
        //initialize semaphore
        bool SetSemValue(const int value);
        bool DeleteSemValue();
        bool SemaphoreP();
        bool SemaphoreV();
        bool SemaphoreOp(const int op);

    private:
        void SetSemBuf(struct sembuf* semb,const int op);
        int semID;
};

#endif

注意union semun可能要自己定义,最好按照手册上的来定义(man semctl)

Semaphore.cpp
Linux 编程 共享内存Linux 编程 共享内存View Code

#include "Semaphore.h"
#include "SemaphoreException.h"
#include <stdio.h>

Semaphore::Semaphore(key_t key,int option)
{
    semID=semget(key,1,option);
    if(semID==-1)
        throw SemaphoreException("Failed to create semaphore");
}

//semaphore should be initialized before use
bool Semaphore::SetSemValue(const int value)
{
    union semun semUnion;
    semUnion.val=value;
    if(semctl(semID,0,SETVAL,semUnion)==-1)
    {
        perror("Failed to initialize semaphore");
        return false;
    }
    return true;
}

bool Semaphore::DeleteSemValue()
{
    union semun semUnion;
    if(semctl(semID,0,IPC_RMID,semUnion)==-1)
    {
        perror("Failed to remove the semaphore set");
        return false;
    }
    return true;
}

bool Semaphore::SemaphoreP()
{
    return SemaphoreOp(-1);
}

bool Semaphore::SemaphoreV()
{
    return SemaphoreOp(1);
}

bool Semaphore::SemaphoreOp(const int op)
{
    struct sembuf semb;
    SetSemBuf(&semb,op);
    if(semop(semID,&semb,1)==-1)
    {
        perror("Failed in semaphore operation");
        return false;
    }
    return true;
}

void Semaphore::SetSemBuf(struct sembuf* semb,const int op)
{
    semb->sem_num=0;
    semb->sem_op=op;
    semb->sem_flg=SEM_UNDO;
}

接下来我们用共享内存的方式简单解决生产者和消费者问题

生产者

//============================================================================
// Name        : sharedMem_Producter.cpp
// Author      : Lei
// Version     :
// Copyright   : 
// Description : sharedMem_Producter in C++, Ansi-style
//============================================================================

#include <iostream>
#include "Semaphore.h"
#include "SharedMemory.h"
#include <string.h>
#include <stdlib.h>
using namespace std;

int main()
{
    int pauseTime;
    void* sharedMemory=static_cast<void*>(0);

    //use semaphore to synchronize processes
    Semaphore semaphore(static_cast<key_t>(1234),READ_WRITE_FLAG | IPC_CREAT);
    semaphore.SetSemValue(1);

    //manager shared memory
    SharedMemory shManager(static_cast<key_t>(1234),sizeof(char)*1024,READ_WRITE_FLAG | IPC_CREAT);
    sharedMemory=shManager.SharedMemoryMat();

    bool running=true;
    while(running)
    {
        if(semaphore.SemaphoreP()==false)
            running=false;

        cout<<"Input your message: ";
        char message[1024];
        cin>>message;
        strcpy(static_cast<char*>(sharedMemory),message);

        if(strcmp(static_cast<char*>(sharedMemory),"end")==0)
            running=false;

        if(semaphore.SemaphoreV()==false)
            running=false;

        pauseTime=rand()%2;
        sleep(pauseTime);
    }

    //delete shared memory
    shManager.DeleteSharedMemory();

    //wait for consumer to release semaphore
    semaphore.SemaphoreP();
    //delete semaphore set
    semaphore.DeleteSemValue();

    return 0;
}

消费者
Linux 编程 共享内存Linux 编程 共享内存View Code

//============================================================================
// Name        : sharedMem_Consumer.cpp
// Author      : Lei
// Version     :
// Copyright   : 
// Description : sharedMem_Consumer in C++, Ansi-style
//============================================================================

#include <iostream>
#include "Semaphore.h"
#include "SharedMemory.h"
#include <string.h>
#include <stdlib.h>
using namespace std;

int main()
{
    int pauseTime;
    void* sharedMemory=static_cast<void*>(0);

    //use semaphore to synchronize processes
    //we had initialized semaphore in producter
    //so we don't call Semaphore::SetValue() here
    Semaphore semaphore(static_cast<key_t>(1234),READ_WRITE_FLAG);

    //manager shared memory
    SharedMemory shManager(static_cast<key_t>(1234),sizeof(char)*1024,READ_WRITE_FLAG);
    sharedMemory=shManager.SharedMemoryMat();

    bool running=true;
    while(running)
    {
        if(semaphore.SemaphoreP()==false)
            running=false;

        cout<<"Press Y/y to read message from producter: ";
        char ch;
        cin>>ch;
        char message[1024];
        strcpy(message,static_cast<char*>(sharedMemory));
        cout<<message<<endl;

        if(strcmp(static_cast<char*>(sharedMemory),"end")==0)
            running=false;

        if(semaphore.SemaphoreV()==false)
            running=false;

        pauseTime=rand()%2;
        sleep(pauseTime);
    }

    shManager.Detach(sharedMemory);

    return 0;
}

原文链接: https://www.cnblogs.com/-Lei/archive/2012/09/18/2691719.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/63175

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 上午10:47
下一篇 2023年2月9日 上午10:48

相关推荐