在同一物理内存位置运行进程



对于一个研究项目,我有一个长时间运行的过程,它使用各种缓冲区和堆栈变量。我希望能够多次启动此过程,以便支持其堆、堆栈、代码和静态变量的物理地址每次都相等。我知道所有这些变量的确切大小,并且堆和堆栈的大小在执行过程中保持不变。为了帮助解决这个问题,我使用一些帮助程序代码将程序中的任意虚拟地址转换为它们相应的物理地址(来源于此处(:

struct pagemap
{
union status
{
struct present
{
unsigned long long pfn : 54;
unsigned char soft_dirty : 1;
unsigned char exclusive : 1;
unsigned char zeroes : 4;
unsigned char type : 1;
unsigned char swapped : 1;
unsigned char present : 1;
} present;
struct swapped
{
unsigned char swaptype : 4;
unsigned long long offset : 50;
unsigned char soft_dirty : 1;
unsigned char exclusive : 1;
unsigned char zeroes : 4;
unsigned char type : 1;
unsigned char swapped : 1;
unsigned char present : 1;
} swapped;
} status;
} __attribute__ ((packed));

unsigned long get_pfn_for_addr(void *addr)
{
unsigned long offset;
struct pagemap pagemap;
FILE *pagemap_file = fopen("/proc/self/pagemap", "rb");
offset = (unsigned long) addr / getpagesize() * 8;
if(fseek(pagemap_file, offset, SEEK_SET) != 0)
{
fprintf(stderr, "failed to seek pagemap to offsetn");
exit(1);
}
fread(&pagemap, 1, sizeof(struct pagemap), pagemap_file);
fclose(pagemap_file);
return pagemap.status.present.pfn;
}
unsigned long virt_to_phys(void *addr)
{
unsigned long pfn, page_offset, phys_addr;
pfn = get_pfn_for_addr(addr);
page_offset = (unsigned long) addr % getpagesize();
phys_addr = (pfn << PAGE_SHIFT) + page_offset;
return phys_addr;
}

到目前为止,我的方法只要求程序中的特定缓冲区在每次运行时位于相同的物理地址。为此,只要该缓冲区的物理地址出错,我就能够退出并重新启动进程,并且每次我都会相对较快地找到正确的位置。但是,我想扩展我的实验,以确保我的进程在运行之间以相同的方式加载到物理内存中,而这种尝试并重新启动方法似乎不适用于此。理想情况下,我希望能够分离出一些无法分配给另一个进程或内核本身的少量物理页面框架。然后,我会将一个标志传递给do_fork,通知内核这是我的特殊进程,并为其分配特定的页面框架。

我的问题是:

  1. 内核中是否已经内置了任何类型的隔离机制,可以让我留出一个可以启动进程的独占物理内存空间?

  2. 如果不是,修改内核以支持此类行为的起点是什么?

  3. 是否有任何其他解决方案(不涉及上述两个中的任何一个(可用于我想要的行为?

这是内核使用虚拟内存的任务是从你身上抽象出来的东西,所以我不确定它是否可能做到(没有疯狂的工作量(。

请问什么实验需要这个?也许如果你描述你想要实现的目标,提供建议会更容易。

最新更新