【问题标题】:How to read & write 1 byte into a particular memory address?如何在特定的内存地址中读取和写入 1 个字节?
【发布时间】:2020-12-31 12:17:12
【问题描述】:

我试图从结构的特定内存地址读取单个字节,然后将相同的字节写入相同的地址。我的目标是将与该内存地址关联的 64 字节内存加载到缓存行中。

我有一个大小为12584 的结构变量testStructure。我尝试使用以下代码将 1 个字节读回内存地址,

unsigned char *p;
int forEachCacheLine = sizeof(testStructure);
printf("size of forEachCacheLine is %d\n", forEachCacheLine);

for (int i = 0; i<forEachCacheLine ; i+=64) {

    printf("i is %d\n",i);

    // read 1 byte 
    p=(unsigned char *)&testStructure+i;
    printf("Read from %p byte is %hhx\n", &testStructure+i, p);


    // write 1 byte
    *(unsigned char *)(&testStructure+i)=p;
    printf("Write into %p byte is %hhx\n\n", &testStructure+i, p);
}

运行代码后,我得到以下输出:

size of forEachCacheLine is 12584
i is 0  
Read from 0x7f5d42e71f80 byte is 80
Write into 0x7f5d42e71f80 byte is 80

i is 64  
Read from 0x7f5d42f36980 byte is c0
Segmentation fault (core dumped)

如输出所示,第一次迭代中的写入尝试成功。但是,第二次迭代会导致Segfault。关于我为什么会收到这个Segmentation fault 的任何信息?

我不太确定这是否是实现我的目标的正确方法。但到目前为止,这是我能想到的唯一方法。如果这是一种不正确的方法,有人可以建议另一种方法吗?

【问题讨论】:

  • p=(unsigned char *)&amp;testStructure+i;之后,p&amp;testStructure+i一样,所以可以printf("Read from %p byte is %hhx\n", p, p);
  • 即使不需要,我也会在指针分配中添加额外的括号。例如,使用p = (&amp;testStructure) + i;
  • 小心指针运算。 (&amp;testStructure+i) 不会在地址中添加i,而是i * sizeof testStructure
  • 在写赋值*(unsigned char *)(&amp;testStructure+i)=p;p不是字节,是指向字节的指针。如果你想写这个指针指向的值,你应该做(&amp;testStructure) + i = *p;。但是,如果这可行,它应该写入相同的字节,因为p 指向与(&amp;testStructure) + i 相同的内存地址,因为之前的分配。

标签: c pointers memory


【解决方案1】:

虽然您的 for 循环似乎每次迭代仅将 i 增加 64 个字节,但您的调试输出显示第二次读取比第一次读取多 805376 个字节 - 这超出了范围,可能导致段错误。 805376 是 12584 的 64 倍。这意味着每次迭代都将 p 增加 64 teststructure,而不是 64 chars

尝试替换

p=(unsigned char *)&testStructure+i; 

p=((unsigned char *)&testStructure)+i;

当我们向其添加i 时,这确保&amp;teststructurechar* 而不是teststructure*

在大多数现代系统上,像这样显式缓存内存几乎没有性能提升。如果您真的想要缓存中的内存 - 请尝试在 teststructure 的每 64 个字节上使用 __builtin_prefetch()。这是一个填充缓存行的 GNU 扩展。您还应该注意它的可选参数。

【讨论】:

  • 感谢示例代码。 @Weather Vane 指出了您提到的相同问题。我仍在努力解决这个问题。您的示例代码对我有帮助。所以,最后对于 1 字节读取我的代码看起来像 p=((unsigned char *)&amp;cacheCryptoEnv)+i; 和写入 1 字节 *(((unsigned char *)&amp;cacheCryptoEnv)+i)=*p;。我得到了我想要的输出。
猜你喜欢
  • 2012-10-11
  • 2015-10-14
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
  • 2012-09-29
  • 1970-01-01
相关资源
最近更新 更多