Linux如何释放内存空间:读写内存空间(write a memory)

我试图写一个签名双号码到内存和读回相同的,读回是冗余的,因为它只是为了验证正确的数据是否在内存中,然后我触发 PL(可编程逻辑)FPGA Fabric 访问此数据并执行任务。

我将一个文件读入 double (union 的一部分),然后通过 unsigned long (union 的一部分) 写入内存。但是写入内存之前和我读出之后的数据是错误的,它只是最后一个字节。(有关详细信息,请参阅代码和注释)

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 上完成的

请帮忙:)

1

你的问题在这里:

    *((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的最低有效字节读取。

如果你做了类似的事情:

    *((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 个字节,并且从其他类型中取消引用指针是(至少有时)未定义的行为。

0

赋值*((unsigned char *) (weights+0x00)) = conv.lw;只写入一个unsigned charSysMem= *((unsigned char *) (weights+0x00));只读取一个unsigned char

要写入和读取double,请使用:

* (double *) weights = conv.dw;
double x = * (double *) weights;
printf("%a\n", x); // Or use %g or %f.

或:

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可以直接使用,而无需将其与unsigned long混叠。

本站系公益性非盈利分享网址,本文来自用户投稿,不代表边看边学立场,如若转载,请注明出处

(934)
Linux虚拟机哪个好用:哪个Linux发行版最适合在虚拟机中运行 用于编程研究
上一篇
Unix网络编程卷2:OSI第 2层网络编程(layer 2 osi)
下一篇

相关推荐

发表评论

登录 后才能评论

评论列表(13条)