c++ - 定义新的内存类型

标签 c++ gcc memory

是否可以定义一种新的内存类型。例如,在某些嵌入式系统编译器中,您可以执行以下操作:

__flash const char array[] = "This is memory in flash (not ram) so I can waste it!";

因此,可以更疯狂地定义一种新型的内存(例如SD卡)。

我基本上是在问是否可以定义什么是SD卡(如何访问其中的数据),然后在sd内存中声明一个变量。 (在看到写入的每个地方都调用sd方法,在看到读取的每个地方都调用sd方法):
class SDCard{
public:
  void write(void* data,size_t length);
  void* read(size_t length);
  void* memAlloc(size_t length);

};

__sd char myVar;  //Grabs an address in the sd card based on SDCard::memAlloc
myVar = 'A';  //Calls whatever I defined the sd card write operation as
char other = myVar;  //Calls whatever I defined the sd card read operation as

如果可以做一些特别的事情,我就在使用gcc(我几乎愿意修改编译器源代码以允许我执行此操作)。

这样的事情是可能的,但是有一些问题:
struct Vol_t{   //Would represent an SD card an external RAM or any other memory
    void write(void* data,size_t len,size_t add) const{}
    void* read(size_t len,size_t add) const{}
};
template<Vol_t* sd, class Type,size_t address>
struct MemDef{  //Wrap your type with this (maybe add -> operator support later
    void operator=(Type&& data){
        sd->write(&data,sizeof(data),address);
    }
    operator Type&(){
        return *reinterpret_cast<Type*>(sd->read(sizeof(Type),address));
    }
};

Vol_t SD;  //Initialize our SD card
MemDef<&SD,int,0xdeadbeaf> sdVar;  //Declare an int variable on the SD card

int main(int argc,char** args){
    sdVar = 12;   //Writes to the SD card
    int local = sdVar;  //Reads from the SD card
    system("Pause");
}

这种方法的问题:
  • Optimizer必须执行每个读取/写入操作– 无法对以此方式声明的变量进行任何优化。 (这是主要问题)
  • 有点不雅(但确实可以完成工作)
  • 您必须指定要使用的内存地址(如果编译器可以在编译之前以某种方式找出所有并自动生成
  • ,那真是太棒了

    因此,也许我必须在gcc中添加一个关键字(如果是这种情况,请指出正确的方向以开始使用)。

    编辑:这种方法还有另一个问题。如果类型具有指向另一个变量的指针,则该变量将不会在SD卡上初始化(只有指针会被初始化)。

    最佳答案

    可能有两种情况:

  • 硬件使得一定范围的地址映射到SD卡,并且可以使用该范围内的常规内存访问指令从SD卡写入/读取数据。使用常规指针。
  • 需要使用特殊指令/功能来读取/写入SD卡。例如,SDCard::read函数(在OS上调用特殊函数,如果有的话)或中断指令。
  • __flash是GCC扩展名。它使用另一条指令访问存储器,并将static数据定位在另一个段上。但是不能单独使用C++以这种方式将其推广。它也不能与动态分配一起使用。

    第一种情况(地址范围)

    要使用常规指针将数据读/写到SD卡,需要将其标记为volatile。这样,编译器不会优化并进行读写操作。 volatile意味着可以从程序外部更改/使用内存,例如,将其写入SD卡的硬件。参见http://en.cppreference.com/w/cpp/language/cv

    例如
    volatile char* data = 0x00010000;
    memcpy(data, "test", 5);
    

    如果内存范围"test" .. 0x00010000映射到SD卡,则将0x0001ffff写在SD卡上。

    要在SD卡上动态分配内存,例如使用mallocfree分配常规工作内存,则需要自定义分配器。它需要自己处理内存分段,即需要映射内存的哪些区域是空闲的或已分配的,并且allocate(len)需要找到长度至少为len的空闲段。这通常由操作系统处理。

    这可以用C++作为分配器类编写,该类必须满足Allocator(概念):http://en.cppreference.com/w/cpp/concept/Allocator的要求。例如(不完整):
    template<typename T>
    class SD_allocator {
        using value_type = T;
        using pointer = T*;
        pointer allocate(std::size_t len) {} // allocate segment of len bytes
        void deallocate(pointer, std::size_t) {}
    };
    

    然后可以与STL容器一起使用,例如:
    std::vector<int, SD_allocator<int>> vec;
    

    将SD卡上的内存用于vec的项目。在这里,它们是非volatile,仅用于程序内部,而不用于SD卡上的持久存储。

    C++中的标准分配器是std::allocator,它分配诸如mallocfree的常规内存。

    Boost似乎在自定义定义的内存区域上提供了一个处理分段的分配器:

    http://www.boost.org/doc/libs/1_35_0/doc/html/interprocess/managed_memory_segments.html
    http://www.boost.org/doc/libs/1_55_0/doc/html/boost/interprocess/allocator.html

    对于SD卡等永久性存储,最好为SD卡上的数据定义固定的结构和布局,然后对其进行读/写。
    struct SDCard_data {
        std::int32_t int1;
        std::int32_t buffer1[500];
        std::int8_t padding_[34];
        int four_bit1 : 4;
        int four_bit2 : 4;
        bool bit1:1;
        bool bit2:1;
        bool bit3:1;
        bool bit4:1;
    };
    
    static volatile SDCard_data* sdcard
        = reinterpret_cast<volatile SDCard_data*>(0x0001000);
    
    int write_to_card() {
        // writes to the card
        card->int1 = 32;
        card->bit3 = true;
    }
    

    第二种情况(特殊说明)

    如果对SD卡的读/写操作与硬件上的常规内存访问指令不符,则无法使用原始volatile指针直接访问其中的数据。

    如果目标仍然是以这种方式访问​​它,则需要一个诸如MemDef的类。最好使用fopenfreadfprintf或类似功能,将SD卡像文件/流一样对待,而不是向其中写入/读取全部数据块。

    为此,需要对对象进行序列化/非序列化。复制struct作为原始内存,例如
    struct A;
    A a;
    write_to_card(reinterpret_cast<void*>(&a), sizeof(A))
    

    只要struct PODType 且不包含任何指针/引用(即其内部表示形式取决于内存地址的类型)就可以工作。它还取决于平台的内存布局(对齐方式,结构填充),字节序,floatCHAR_BIT的表示等。对于跨平台支持(例如,当从具有另一种微 Controller 的另一台设备读取SD卡时,某些文件格式)将需要代替使用。

    定义自定义Allocator类也是可能的(但很困难),该类将MemDef之类的类用作指针类型。

    关于c++ - 定义新的内存类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36657662/

    相关文章:

    在内存中复制一个函数并执行它

    memory - OpenCL:使用什么类型的内存?

    python - Sklearn.KMeans : how to avoid Memory or Value Error?

    c++ - 静态分配的可变大小数组如何在 C++ 中工作?

    c++ - 如何检测是否显示 Metro UI?

    c++ - unordered_set C++

    c++ - 由于 QCoreApplication 事件循环,QThread 永远不会退出

    gcc - golang 在使用和不使用 cgo 进行构建时使用的汇编程序

    c++ - 宏替换,-E 选项 gcc

    gcc - 引导构建 gcc - 第 2 阶段和第 3 阶段比较失败