【问题标题】:How to make a struct stored in two different memory pages in linux kernel?如何使结构存储在linux内核的两个不同内存页中?
【发布时间】:2016-07-26 11:26:54
【问题描述】:

我英语不好,我会尽力把问题说清楚。

假设我有一个结构是:

struct A {
   /* the first half */
   int a;
   int b;
   /* the second half */
   int c;
   int d;
} ;

我们知道 A 的成员会连续存储在内存中。但是,我想让 A 的前半部分和后半部分存储在两个不同的内存页中,这意味着该结构在内存中进行了分区。我怎样才能实现它?
假设 struct A 是 linux 内核中的一个结构,所以我在内核空间中编程。内核版本是3.10。

更新:为了明确目标,我画了下图,就是我想要的内存布局,这样可以避免内存空间的浪费:

【问题讨论】:

  • 出于所有合理的目的,你不能在 C 中这样做。
  • align 宏或 __attribute__((align()) 怎么样?这有用吗?@DavidHoelzer
  • 你为什么要这样做??
  • 出于某些安全目的。@MichaelWalz
  • 将其填充至 2 倍页面大小并与页面大小对齐。

标签: c gcc memory-management struct linux-kernel


【解决方案1】:

如果目标是使结构内存不连续,请使用指针并执行 kmalloc。

struct first_half  {
 int a;
 int b;
};

struct second_half {
int c;
int d;
};    


 struct A {
    /* the first half */
    struct first_half *fh;
    /* the second half */
    struct second_half *sh;
 } ;

 fh = (struct first_half *) kmalloc();
 sh = (struct second_half *) kmalloc();

【讨论】:

  • 请注意这里不需要强制转换,void* 隐式转换为 C 中的任何指针。
  • 注意A是内核结构,如果这样改的话,很多引用A的内核代码都要改。
【解决方案2】:

您可以通过在结构的成员之间添加填充并将其分配在页面边界上来做到这一点,例如:

struct A {
    int a, b;
    char padding[PAGE_SIZE - 2 * sizeof(int)];
    int c, d;
};

但是,它只处理一种大小的页面(例如 4KB),而有不同大小的大页面(x86_64 上为 2MB 和 1GB)。

或者,如果不需要填充,请以这样的方式为结构分配内存,以便对象跨越页面边界。

【讨论】:

  • 感谢您的精彩回答!有没有办法可以使用填充的内存空间来存储另一个结构 A 而不是浪费它?
  • @hexiecs 你可以把任何你喜欢的东西放在填充中。不过,了解 C 和结构内存布局是任何类型软件安全的先决条件。
  • 你好,请看更新,是我想要的内存布局。
  • @hexiecs 这基本上是两个不同页面上的两个不同structs 的数组。将您的 struct 分成两部分,并使用相同的索引来访问来自不同数组的关联元素(一半)。
  • 你好,正如我在其他cmets中提到的那样,破坏结构并不是那么好,因为与结构A相关的其他代码必须在linux内核中进行更改。
猜你喜欢
  • 2011-05-14
  • 2020-10-09
  • 2023-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-03
  • 2016-10-19
  • 2017-10-28
相关资源
最近更新 更多