定义新类型的内存

Dar*_*bik 23 c++ memory gcc

是否可以定义新类型的内存.例如,在某些嵌入式系统编译器中,您可以这样做:

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

因此可能更疯狂并定义一种新型存储器(比如说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
Run Code Online (Sandbox Code Playgroud)

我正在使用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");
}
Run Code Online (Sandbox Code Playgroud)

这种方法的问题:

  • 优化器必须执行每一次读/写操作----它不能对以这种方式声明的变量进行任何优化.(这是主要问题)
  • 它有点不雅(但它确实完成了工作)
  • 你必须指定要使用的内存地址(如果编译器能够以某种方式编译之前以某种方式计算出所有这些内容并且会自动生成,这将是非常棒的

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

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

tml*_*len 8

可能有两种情况:

  1. 硬件使得一定范围的地址映射到SD卡,并且可以使用该范围内的正常存储器访问指令从SD卡写入/读取数据.使用常规指针.
  2. 需要使用特殊指令/功能来读/写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);
Run Code Online (Sandbox Code Playgroud)

写入"test"SD卡,如果例如内存范围0x00010000.. 0x0001ffff映射到它.

动态分配内存的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) {}
};
Run Code Online (Sandbox Code Playgroud)

如果可以与STL容器一起使用,例如:

std::vector<int, SD_allocator<int>> vec;
Run Code Online (Sandbox Code Playgroud)

使用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;
}
Run Code Online (Sandbox Code Playgroud)

第二种情况(特别说明)

如果对SD卡的读/写与硬件上的常规存储器访问指令不对应,则无法使用原始volatile指针直接访问其上的数据.

如果目标仍然是以这种方式访问​​它,MemDef那么将需要一个类.这可能是更好的治疗SD卡就像一个文件/流,而是写/从中读取数据的整个块到/,使用类似功能fopen,fread,fprintf或类似的.

对象需要为此序列化/反序列化.复制struct原始内存,如

struct A;
A a;
write_to_card(reinterpret_cast<void*>(&a), sizeof(A))
Run Code Online (Sandbox Code Playgroud)

只要struct是a PODType并且不包含任何指针/引用,即内部表示取决于内存地址的类型.它也依赖于平台的存储器布局(取向,结构填充),字节序,的表示float,CHAR_BIT等.对于跨平台的支持(例如,当SD卡从与另一个微控制器的另一设备读取,某些文件格式将需要用来代替.

也许(但很难)定义一个自定义Allocator类,它使用类似MemDef指针类型的类.