为什么无法访问自 Windows 95 以来另一个进程的地址空间?

Why can't you access the address space of another process since Windows 95?

本文关键字:另一个 进程 地址空间 访问 Windows 为什么      更新时间:2023-10-16

假设我将一个指针作为参数发送给另一个程序:

program.exe -mypointer

并尝试在那个程序中使用它,它不会工作。经过一些研究(例如在Lounge c++上询问),我发现从Windows 95开始,你不能访问其他程序的地址空间。在旧版本的Windows中,这是允许的。我的问题是,为什么微软不允许呢?这样做的问题或缺点是什么?

p。在新版本的Windows中,是否仍然有可能通过一些变通来做到这一点?

因为能够访问其他进程的地址空间意味着您可以通过例如随机更改它们的内存内容使它们崩溃。

保护模式的全部是保护进程之间的相互影响。请参阅内存保护维基百科页面了解更多细节。在没有保护之前的糟糕日子里,编写干扰其他进程的代码要容易得多。

这样做的缺点是,对于一些Word中的bug来说,不仅会使Word崩溃,还会使Excel、Borland C、你运行了六周的PI数字计算器甚至操作系统本身崩溃。

您仍然可以访问另一个进程地址空间,但是您基本上必须以更高的权限运行才能这样做。例如,这就是调试器允许您运行进程并访问其所有内存以进行调试的方式。

调用ReadProcessMemoryWriteProcessMemory允许您这样做,以及许多其他调试功能。

16位Windows在内存管理方面确实取得了一些惊人的成就,但由于它是为没有内存管理的处理器设计的,即最初PC的i8086(硬件人员可能会注意到最初的PC使用的是i8088,除了数据总线的宽度之外,它们是相同的)。

所以,在16位的Windows进程共享相同的内存视图。

这样做的一个问题是,当无数进程想要拥有它们自己的内存块时,公共内存地址空间并不是那么大。

此外,它使进程很容易互相绊倒。

Windows提供了一些部分的解决方案,比如一个进程可以通知Windows它什么时候实际使用了一些内存(这个进程随后会"锁定")。这意味着Windows可以在需要的时候移动内存内容来腾出空间,但这都是自愿的,而且也不是很安全。

因此,32位的Windows,即Windows NT,利用较新的处理器的内存管理来自动执行16位Windows程序应该使用的最佳实践。实际上,进程只处理逻辑地址,处理器自动将其转换为物理地址(进程永远看不到)。嗯,在32位PC上,转换是两步的事情,也就是说,有一个内部的中间地址形式,但这是你不需要知道的复杂性。

这种硬件支持的地址转换的一个很好的结果是进程可以完全与它使用的物理地址的知识隔离。例如,同一个程序很容易有两个进程。他们认为他们在处理相同的地址,但那些只是逻辑地址;实际上,它们的逻辑地址被转换成不同的物理地址,这样它们就不会践踏彼此的内存区域。

和一个后果,我们20-20后见之明可以说不是那么好,是翻译方案允许虚拟内存,例如,模拟RAM通过使用磁盘空间。Windows可以将内存内容复制到磁盘,然后将该物理内存区域用于其他用途。当使用该内存区域的进程写入或读取该内存区域时,Windows会进行一些狂热的活动,将数据从磁盘加载回某个内存区域(可能是相同的,也可能是其他的),并在那里映射进程的逻辑地址。这样做的结果是,在低内存条件下,个人电脑从一个电子畜生变成了一个机械畜生,运行速度慢了成千上万倍。不好——但是当RAM很小的时候,人们认为虚拟内存很简洁。

在今天的Windows中,虚拟内存的主要问题是,在实践中,几乎不可能关闭那该死的东西。即使只有一个"主"。程序正在运行,并且可用的物理内存远远超过足够的内存,Windows将主动将数据交换到磁盘,以便在进程可能需要更多逻辑内存时做好准备。然而,如果这是固定的,那么其他东西很可能会出现在它的代替;这就是宇宙的本质

你的前提不正确。在Windows中,你当然可以读取另一个进程的内存。你不能通过解引用指针来实现,因为每个进程都有不同的内存视图。出于各种原因,这是必要的,但最重要的原因是防止一个程序中的错误破坏其他正在执行的程序。(另一个是防止地址空间成为稀缺资源)

听起来好像你认为内存保护是一件坏事!?

不受控制地访问一个进程的内存通常会导致错误、崩溃、未定义的行为,更严重的是,可能会为恶意软件和病毒打开大门。您可以编写两个通过共享内存很好地协作的进程,但同样,任何其他进程,无论是错误的还是恶意的,都可以访问它。此外,它也很容易丢弃操作系统内核本身。

Win16最初是作为一个图形环境运行的,而不是MS-DOS之上的一个真正的操作系统,设计用于早期的16位x86处理器,没有MMU来允许内存保护。Win32S API后来被引入到Windows 3中。它在Win16上提供了Win32特性的子集。Windows32(最初是Windows NT,然后同时是Windows 95)利用80386引入的特性,为每个进程提供自己的内存环境,除非受到邀请,否则其他进程不可见。

这就是使Windows NT比Win3.x更健壮的原因。Windows 95并没有充分利用保护机制,可能是为了某种程度的向后兼容性,所以虽然比Win3更健壮。Windows XP是第一个使用Windows NT/Windows 2000代码库的"消费者"Windows操作系统,并且抛弃了大部分(但不是全部)Windows 95/MS-DOS兼容性包袱。

如果您希望在进程之间共享数据,正确的方法是通过任何公认的IPC机制。一种这样的方法实际上是通过内存映射文件,它实际上是一个共享内存块,但是具有访问控制,因此不是任何进程都可以看到内存。

如果你可以在其他进程的ram区域搞砸,那么很容易使它崩溃。例如,你只需要设置一些指针为NULL,进程就会消失。RAM是每个进程的"私有"部分,您不希望任何人访问它们,不是吗?是的,如果你做一些内核调试,可能有一些方法可以访问它