首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对内存空间的读写

对内存空间的读写
EN

Stack Overflow用户
提问于 2019-05-23 07:12:53
回答 2查看 530关注 0票数 1

我正在尝试将一个带符号的双精度数写入内存并读回相同的数字,读回是多余的,因为它只是为了在触发PL (可编程逻辑) FPGA结构访问该数据和执行任务之前验证内存中是否存在正确的数据。

我将文件读入双精度(联合的一部分),然后通过无符号的长整型(联合的一部分)写入内存。但是在写入内存之前和我读出之后的数据是错误的,它只是最后一个字节。(详细信息请参见代码和注释)

代码语言:javascript
运行
复制
union floatpun {
    double dw;
    unsigned long lw;
};

void *lookup_slave_by_phy_addr(const int fd, const off_t target, const size_t mapsize)
{
  void *map_base, *virt_addr;

  /* Map one page */
  map_base = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~(mapsize-1));
  if (map_base == (void *) -1) { FATAL; }
  printf("Memory mapped at address %p.\n", map_base);
  fflush(stdout);

  virt_addr = map_base + (target & (mapsize-1));
  return virt_addr;
}


int main(int argc, char *argv[])
{  
  union floatpun conv;

  FILE *fp;
  fp = fopen("/media/card/numbers.txt", "r");
  fscanf(fp,"%lf",&conv.dw);  // 0.009101592004299160 Reads this number from the file, which is correct as expected.
  printf("The value Read from the File is %lx \n",conv.lw); // Prints 3f 82 a3 da ff ff ff fe, which is also correct.
  fclose(fp);

  int fd;
  if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { FATAL; }
  printf("/dev/mem opened.\n");
  fflush(stdout);

  void *weights;
  // Map systemMemory master phy address range 0000 0008 7000 0000 -> 0000 0008 7FFF FFFF
  weights       = lookup_slave_by_phy_addr(fd,strtoul("0x0000000870000000",0,0),MAP_SIZE_256M);
    *((unsigned char *) (weights+0x00))  = conv.lw;   // Writing into the mempory
    SysMem= *((unsigned char *) (weights+0x00));    // Reading it out from the memory
    printf("Read %lx\n", SysMem);                   // When this is printed I get only FE, the last byte of the data read from the file, I have read the following 0x01, 02 03 also, which are all junk data like 0x69 0x95 0x9A

  close(fd);
  return 0;
}

我在向内存写入或从内存读取时犯了什么错误,我想要将这个完整的64位写入内存。或者我应该手动将每个字节写入内存的一个字节,而内存字(32位)是不可寻址的?或者,如果不是,我可以使它成为一个可寻址的单词吗?

此外,这也是在Zynq上使用Petalinux完成的

请帮助:)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-23 09:30:26

你的问题在这里:

代码语言:javascript
运行
复制
    *((unsigned char *) (weights+0x00))  = conv.lw;   // Writing into the mempory
    SysMem= *((unsigned char *) (weights+0x00));    // Reading it out from the memory

(void *) weights转换为(unsigned char *),然后将conv.lw的值存储在该指针位置。

但是通过进行类型转换,您已经显式地告诉编译器您只想编写单个unsigned char,所以它很乐意用conv.lw的最低有效字节来实现这一点。

类似地,当您读回它时,您再次将weights转换为(unsigned char *),因此您只能从该位置读取单个字节。

如果你做了类似这样的事情:

代码语言:javascript
运行
复制
    *((unsigned long *) (weights+0x00))  = conv.lw;   // Writing into the mempory
    SysMem= *((unsigned long *) (weights+0x00));    // Reading it out from the memory

您将写入和读取conv.lw的所有字节。

还有一些原因使得你要做的事情是不可移植的,包括:unsigned long在32位架构上通常只有4个字节,从其他类型转换的指针是(至少有时)未定义的行为。

票数 1
EN

Stack Overflow用户

发布于 2019-05-23 09:41:33

赋值*((unsigned char *) (weights+0x00)) = conv.lw;仅写入单个unsigned char,而SysMem= *((unsigned char *) (weights+0x00));仅读取单个unsigned char

要写入和读取double,请使用以下任一方法:

代码语言:javascript
运行
复制
* (double *) weights = conv.dw;
double x = * (double *) weights;
printf("%a\n", x); // Or use %g or %f.

或者:

代码语言:javascript
运行
复制
memcpy(weights, conv.dw, sizeof conv.dw);
double x;
memcpy(x, weights, sizeof x);
printf("%a\n", x); // Or use %g or %f.

第一种方法要求weights与您的平台适当地对齐(看起来像是在您的示例代码中)。不应该直接从这段代码中产生别名问题,因为conv.dw是作为它的适当类型(double)来访问的,而weights实际上是一个动态分配的对象(提供获取它的值的代码是正确的,想必您的编译器也支持这一点),所以可以通过在weights中编写一个double来有效地创建一个double

如果在您的进程中可以正确访问weights中的地址,那么无论对齐与否,第二种方法都应该有效。

在任何一种情况下,都不需要联合。可以直接使用double,而无需使用unsigned long作为别名。

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

https://stackoverflow.com/questions/56266114

复制
相关文章

相似问题

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