了解操作系统中的虚拟内存:概念和实现
运行内存分配程序的多个实例时出现意外行为。
我正在学习操作系统并遵循 OSTEP(操作系统:三个简单的部分)教科书。我试图通过同时运行程序的多个实例来理解内存虚拟化。这是我正在使用的代码:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
int main(int argc, char *argv[]) {
int *p = malloc(sizeof(int)); // a1
assert(p != NULL);
printf("(%d) address pointed to by p: %p\n", getpid(), p); // a2
*p = 0; // a3
while (1) {
Spin(1);
*p = *p + 1;
printf("(%d) p: %d\n", getpid(), *p); // a4
}
return 0;
}
根据教科书,当使用命令
./mem &; ./mem &
运行时,该程序应通过同时运行两个实例来演示内存虚拟化。文中写道:
我们从示例中看到,每个正在运行的程序都在同一地址(0x200000)分配了内存,但每个程序似乎都在独立更新 0x200000 处的值!就好像每个正在运行的程序都有自己的私有内存,而不是与其他正在运行的程序共享相同的物理内存。事实上,这正是这里发生的情况,因为操作系统正在虚拟化内存。
但是,当我在本地运行该程序时,我得到以下输出:
PS C:\Users\malan\Desktop\os\Virtualizing_the_Cpu> ./mem &; ./mem
Id Name PSJobTypeName State
-- ---- ------------- -----
13 Job13 BackgroundJob Running
(8776) address pointed to by p: 007B1990
(8776) p:1
(8776) p:2
(8776) p:3
(8776) p:4
(8776) p:5
(8776) p:6
(8776) p:7
(8776) p:8
(8776) p:9
(8776) p:10
(8776) p:11
(8776) p:12
(8776) p:13
两个实例未按预期同时运行。什么可能导致这种行为?我是否在设置或理解中遗漏了某些内容?
附加信息:
将其输入 bash 即可运行。
& 在 bash 中表示后台运行,但在 powershell 中表示其他含义;我很惊讶你没有收到错误消息。
命令末尾的
&
是 bash 指令(即 Linux / Unix 命令行),用于在后台运行程序。 Windows下没有这个功能。
最简单的方法是调出两个单独的命令提示符,并大致同时在每个命令提示符中运行程序。
tl;博士
在 PowerShell (Core) 7(您正在运行的)中,使用以下命令:
(./mem &), (./mem &) | Receive-Job -Wait -AutoRemoveJob
在 Windows PowerShell(旧版 Windows 附带版本,最新且最后一个版本为 5.1):
(Start-Job { ./mem }), (Start-Job { ./mem }) | Receive-Job -Wait -AutoRemoveJob
./mem &; ./mem &
命令行适用于Bash:
PowerShell (Core) 7 中也在语法上有效(尽管 在 Windows PowerShell 中不,它仅支持 Start-Job
,见下文),但的功能不同:
&
,后置背景运算符,是
Start-Job
调用的语法糖(./mem &
是
Start-Job { ./mem }
的缩写),并创建 PowerShell 背景job,以及这些调用的内容return 是一个作业 object,可以使用 cmdlet 进行查询和管理,例如
Receive-Job
。
大致类似于 Bash 工作,但也有重要的区别:
不会自动打印到调用者的终端;相反,输出是在幕后悄悄收集的,并且可以根据需要使用 Receive-Object
手动清理(删除),可以通过Remove-Job
-AutoRemoveJob
传递给
Receive-Job
(这也需要
-Wait
同步等待作业)完成,以便可以收集其所有输出)。