0

我正在尝试使用在共享内存中实例化的缓冲区类。有一个唯一的写入器进程写入共享内存中的该对象,以及一个唯一的读取器(因此无需使用同步)。

有人能指出为什么从共享内存中读取是意外值吗?请注意,下面的源代码是使用 g++ 编译器在运行 Debian Linux 的 32 位机器上编译和测试的。

我编写了一个测试最小示例,文件如下所示。模板缓冲区类头文件:

// file testbuffer.h
#ifndef _TESTBUFFER_H_
#define _TESTBUFFER_H_

#include <iostream>
#include <cstring>


//our data type
typedef struct tagSTT{
    int x;
    float y;
    char c;
} STT;

#define DATANUM 2048



template <typename T, int nCapacity >
    class CBuff {
 public:
    CBuff ();
    ~CBuff ();
    bool pop(T *  pVal);
    bool push(T const * const pVal);
 private:
    /*! memory buffer*/
    T *m_pBuff;
    T m_aBuff[nCapacity];
    volatile int m_nCapacity;
    //Read index. Always points to the item index right after the previously read. Initially = 0.
    volatile int m_nR;
    //Write index. Always points to the location right after the previously written to. Initially = 0.
    volatile int m_nW;
};

template <typename T, int nCapacity >
    CBuff<T, nCapacity>::CBuff () {
    m_pBuff = NULL;
    m_nCapacity = nCapacity;
    m_nR = 0;
    m_nW = 0;
    m_pBuff = m_aBuff;
    memset((void *)m_pBuff, 0, sizeof(T) * m_nCapacity);
}

template <typename T, int nCapacity >
    CBuff<T, nCapacity>::~CBuff(){
}

template <typename T, int nCapacity >
    bool CBuff<T, nCapacity>::pop(T *  pVal) {
    if (m_nR == m_nW){//nothing new to read
        return false;
    }
    int nNextR = (m_nR + 1) % m_nCapacity;
    (*pVal) = m_pBuff[m_nR];
    m_nR = nNextR;
    return true;
}
template <typename T, int nCapacity >
    bool CBuff<T, nCapacity>::push(T const * const pVal){
    int nNextW = (m_nW + 1) % m_nCapacity;
    if (nNextW != m_nR) {//buffer is not full
        m_pBuff[m_nW] = *pVal;
        m_nW = nNextW;
        return true;
    }
    return false;
}
#endif 

接下来,这里是创建共享内存的程序文件,在该内存中实例化缓冲区,然后将一些测试数据启动到缓冲区中。

//Test program. *Only* writes to the shared memory buffer. 
//Comile with:
// g++ -g -pedantic -Wall -I ./ fillbuff.cpp -o fillbuff -lrt

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <pthread.h>


#include <testbuffer.h>


int main(int argc, char ** argv) {
    CBuff < STT, DATANUM> DBuff;//to get size of our whole data object
    CBuff < STT, DATANUM> *pDBuff = NULL;

    int fd = 0;
    char ShmName[1024];
    bzero(ShmName, sizeof(ShmName));
    strcpy(ShmName, "/MyShm");
    size_t ShmSize = sizeof(DBuff);

    shm_unlink(ShmName);//incase it is lying around after a previous crash
    fd = shm_open(ShmName, O_RDWR | O_CREAT | O_TRUNC, 0666);
    if (fd < 0){
        return -10;
    }
    //set the size of the shared mem ob
    if (ftruncate(fd, ShmSize) == -1){
        return -11;
    }

    CBuff < STT, DATANUM> *pShm = NULL; 
    //map the file into the address space of the process
    pShm = (CBuff < STT, DATANUM> *) mmap(0, ShmSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (pShm == (CBuff < STT, DATANUM> *)-1){
        std::cerr << "ERROR mapping GUI shared memory" << std::endl;
        return -12;
    }
    pDBuff = new (pShm)CBuff < STT, DATANUM>;

    STT Data;
    memset((void *)&Data, 0, sizeof(STT));
    std::string sTmp;
    int n = 0;
    //start population data inout our buffer
    for (n = 0; n < 29; n++) {
        Data.x = n;
        Data.y = float(n)/100;
        Data.c = 'R';
        std::clog << Data.x << " " 
                  << Data.y << " " 
                  << Data.c << std::endl;
        if (pShm->push(&Data) == false){
            std::cerr << "Could not push data sample " << n << " on to CB" << std::endl;
        } 
        usleep(500000);//wait
    }

    pDBuff->~CBuff();
    //unmap the memory
    if (munmap(pShm, ShmSize) < 0){
        std::cerr << "ERROR unmapping common memory" << std::endl;
        return -20;
    }
    close (fd);
    shm_unlink(ShmName);



    return 0;
}

最后,这个必须在上述程序启动后启动的程序,从共享内存中读取值并打印出来。读取的值不是我保存在上面的缓冲区填充器中的值。我在这里想念什么?谢谢。

//Test program, *only* read from the shared memory buffer.
//compile with:
//g++ -g  -Wall -I ./ emptybuff.cpp -o emptybuff.cpp -o emptybuff  -lrt
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <pthread.h>

#include <testbuffer.h>

int main () {

    char ShmName[1024];
    bzero(ShmName, sizeof(ShmName));
    strcpy(ShmName, "/MyShm");
    size_t ShmSize = sizeof(CBuff < STT, DATANUM>);
    int fd = shm_open(ShmName, O_RDWR, 0666);
    if (fd < 0){
        std::cerr << "Could not get a fd." << std::endl;
        return -10;
    }
    CBuff < STT, DATANUM> *pBuff = NULL;
    STT D;//will hold a sample
    pBuff = (CBuff < STT, DATANUM> *) mmap(0, ShmSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (pBuff == (CBuff < STT, DATANUM> *) -1){
        std::cerr << "Could not map shm" << std::endl;
        return -1;
    }
    //read off the data from the buffer (which should already be filling up)
    int k = 0;
    for (k = 0; k < 10; k++) {
        pBuff->pop(&D);//get a sample from the buffer
        //print it out
        std::clog << D.x << " " 
                  << D.y << " " 
                  << D.c << std::endl;
        usleep(750000);//wait and lag behind the buffer filler process.
    }
    close (fd);
    shm_unlink(ShmName);

    return 0;
}
4

0 回答 0