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

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;

}

消费者

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;

}

你可能感兴趣的:(linux)