首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >定义新类型的内存

定义新类型的内存
EN

Stack Overflow用户
提问于 2016-04-15 22:11:37
回答 2查看 1.2K关注 0票数 23

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

代码语言:javascript
复制
__flash const char array[] = "This is memory in flash (not ram) so I can waste it!";

因此,是否有可能更疯狂地定义一种新类型的内存(比如SD卡)。

我基本上是在问,是否可以定义SD卡是什么(如何访问其中的数据),然后在sd内存中声明一个变量。(每次看到它调用sd方法的写入,每个地方都看到它调用sd方法的读):

代码语言:javascript
复制
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,如果我可以用它做一些特别的事情(我几乎愿意修改编译器源代码以允许我这样做)。

像这样的事情是可能的,但是有几个问题:

代码语言:javascript
复制
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");
}

这种方法的问题:

  • 优化器必须完成每一个读/写--它不能对以这种方式声明的变量进行任何优化。(这是主要问题)
  • 这是有点不雅(但它确实完成了工作)
  • 您必须指定要使用的内存地址(如果编译器能够在编译之前自动计算出所有这些地址,那就太棒了。)

所以也许我必须给gcc加上一个关键词(如果是这样的话,请指出正确的方向开始)。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-19 17:08:25

可能有两种情况:

  1. 硬件是这样的,在这个范围内,一定范围的地址映射到SD卡,并且可以使用正常的存储器访问指令从SD卡中写入/读取数据。使用常规指针。
  2. 需要使用特殊的指令/功能来读/写SD卡。例如,一个SDCard::read函数,它在操作系统上调用一个特殊函数(如果有的话),或者一个中断指令。

__flash是GCC的扩展。它使用不同的指令来访问内存,并在另一个段中定位static数据。但是,不能仅使用C++以这种方式进行推广。它也不能用于动态分配。

第一种情况(地址范围)

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

例如

代码语言:javascript
复制
volatile char* data = 0x00010000;
memcpy(data, "test", 5);

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

要在SD卡上动态分配内存,就像使用mallocfree为常规工作内存分配一样,需要一个自定义分配器。它需要处理内存分段本身,即它需要映射内存的哪些区域是空闲的或分配的,而allocate(len)需要找到长度至少为len的空闲段。这通常由操作系统来处理。

这可以用C++作为一个分配器类来编写,这个类必须满足Allocator (概念):http://en.cppreference.com/w/cpp/concept/Allocator的要求。例如(不完整):

代码语言:javascript
复制
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容器一起使用,如:

代码语言:javascript
复制
std::vector<int, SD_allocator<int>> vec;

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

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

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

segments.html 0/doc/html/boost/interprocess/allocator.html

对于诸如SD卡之类的持久存储,最好为SD卡上的数据定义一个固定的结构和布局,然后对其进行读写。

代码语言:javascript
复制
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这样的类。最好将SD卡作为文件/流来对待,并使用fopenfreadfprintf或类似的函数将整块数据写入/读取其中。

为此,需要对对象进行序列化/非序列化。将struct复制为原始内存,如

代码语言:javascript
复制
struct A;
A a;
write_to_card(reinterpret_cast<void*>(&a), sizeof(A))

只要struct是一个PODType,并且不包含任何指针/引用,即内部表示依赖于内存地址的类型就可以工作。它还依赖于平台的内存布局(对齐、结构化填充)、endianness、floatCHAR_BIT等跨平台支持(例如,当SD卡从另一个带有另一个微控制器的设备读取时,需要使用某种文件格式。

也可能(但很难)定义一个自定义Allocator类,它使用像MemDef这样的类作为指针类型。

票数 8
EN

Stack Overflow用户

发布于 2016-04-19 02:59:27

在C++世界中,为了抽象内存,通常需要编写一个自定义分配器。沿着线

代码语言:javascript
复制
template <class T>
class SDAlloc {
 public:
   typedef T        value_type;
   typedef T*       pointer;
   typedef const T* const_pointer;
   typedef T&       reference;
   typedef const T& const_reference;
   typedef std::size_t    size_type;
   typedef std::ptrdiff_t difference_type;

   // rebind allocator to type U
   template <class U>
   struct rebind {
       typedef SDAlloc<U> other;
   };

   // return address of values
   pointer address (reference value) const {
       return &value;
   }
   const_pointer address (const_reference value) const {
       return &value;
   }

   SDAlloc(const char* device) {
       // open device by name
       // make helper structures
   }
   ~SDAlloc() {
       // close device
   }

   // return maximum number of elements that can be allocated
   size_type max_size () const throw() {
       return SDsize;
   }

   // allocate but don't initialize num elements of type T
   pointer allocate (size_type num, const void* = 0) {
       // print message and allocate memory on SD
   }

   .......
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36657662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档