假设我把一个指针作为参数发送给另一个程序:
program.exe -mypointer
并尝试在该程序中使用它,它将无法正常工作。 经过一些研究(例如,在Lounge C ++询问)后,我发现从Windows 95开始,你不能访问另一个程序的地址空间。 在旧版本的Windows中,它被允许。 我的问题是,为什么微软不允许这样做? 这样做有什么问题或缺点?
PS是否仍然可以通过一些解决办法在新版本的Windows中执行此操作?
因为能够访问其他进程的地址空间意味着你可以通过例如随机地改变它们的内存内容来使它们崩溃。
保护模式的重点在于互相保护流程。 有关更多详细信息,请参阅内存保护维基百科页面 。 在保护之前的恶劣日子里,编写与其他进程混淆的代码要容易得多。
不足之处在于,对于MS Word中的一些错误,不仅会使MS Word崩溃,而且Excel,Borland C,过去六周运行的PI数字计算器甚至操作系统本身。
您仍然可以访问另一个进程地址空间,但基本上必须以更高的权限运行才能执行此操作。 例如,这是调试器如何让你运行一个进程并访问所有内存以进行调试。
调用ReadProcessMemory
和WriteProcessMemory
允许您执行此操作以及其他许多调试功能 。
16位Windows做了一些真正惊人的内存管理的专长,但是它被设计用于没有内存管理的处理器,即原始PC的i8086(硬件人可能不是说原来的PC使用了一个i8088,这是相同的数据总线的宽度除外)。
所以,在16位Windows进程中共享相同的内存视图。
其中一个问题就是,公用内存地址空间并不是那么大,实际上,当很多进程想拥有自己的块时。
另外,它使得进程相互之间很容易绊倒彼此的脚。
Windows提供了一些部分的解决方案,例如一个进程通知Windows它实际上使用某些内存的时间(这个过程会“锁定”内存区域),这意味着Windows可以移动内存内容以腾出空间需要的,但是都是自愿的,也不是很安全。
因此,32位Windows,Windows NT利用较新的处理器的内存管理来自动化16位Windows程序应该使用的最佳实践。 本质上,一个进程只处理逻辑地址 ,处理器自动将其转换为物理地址 (进程永远不会看到的地址 )。 那么,在32位PC上,翻译是一个两步的事情,即有一个内部的中间地址表单,但这是你不需要知道的复杂情况。
这种硬件支持的地址转换的一个很好的结果就是一个进程可以完全不知道它使用哪个物理地址。 例如,同一个程序中有两个进程很容易。 他们认为他们正在处理相同的地址,但这些地址只是逻辑地址; 实际上,它们的逻辑地址被转换为不同的物理地址,所以它们不会在彼此的存储区域上跺脚。
其中一个后果就是20-20事后我们可以说不太好,就是翻译方案允许使用虚拟内存 ,例如通过使用磁盘空间来模拟内存。 Windows可以将内存内容复制到磁盘,然后将该区域的物理内存用于其他内容。 当使用内存区域的进程写入或读取进程时,Windows进行一些狂热的活动,将数据从磁盘加载回某些内存区域(可能是相同的或其他),并映射进程的逻辑地址那里。 其结果是,在低内存条件下,电脑从电子化转变为机械化,表现出数千万倍的低功耗。 Ungood – 但是当内存大小很小时,人们认为虚拟内存是整齐的。
在今天的Windows中,虚拟内存的主要问题是在实践中几乎不可能把这件事情关掉。 即使只有一个“主”程序在运行,并且有足够多的物理RAM可供使用,Windows也会主动将数据交换到磁盘,以备可能需要更多逻辑内存的情况下使用。 但是,如果这是固定的,那么其他的东西很可能会代替它。 这就是宇宙的本质。
干杯&hth。,
你的前提是不正确的。 你当然可以在Windows中读取另一个进程的内存 。 你不能这样做,因为每个进程都有不同的内存视图。 这是由于各种原因所必需的,但最重要的是防止一个程序中的错误破坏其他执行程序。 (另一个是防止地址空间成为稀缺资源。)
你听起来像你认为记忆保护是一件坏事!?
一个进程的内存不受控制地从另一个进程访问通常会导致错误,崩溃,未定义的行为,更关键的可能是对恶意软件和病毒的开放门户。 您可以编写两个通过共享内存很好地协作的进程,但同样,任何其他进程都可能通过错误或恶意方式访问它。 而且,也很容易把操作系统内核本身破坏掉。
Win16最初是作为一个图形环境运行的,而不是MS-DOS上的一个真正的操作系统,并被设计为在没有MMU的早期的16位x86处理器上工作以允许内存保护。 Win32S API是在Windows 3.x中引入的,后者在Win16上提供了Win32功能的子集。 Windows32(最初是Windows NT,然后是Windows 95)利用了80386中引入的功能,为每个进程提供了自己的内存环境,除了邀请之外,其他任何进程都是不可见的。
这是什么使Windows NT更稳健的Win3.x. Windows 95并没有充分利用这种保护机制来推测某些级别的向后兼容性,所以虽然Win3.x更强大,但几乎没有NT那样的防崩效果。 Windows XP是第一个使用Windows NT / Windows 2000代码库的“消费者”Windows操作系统,并且放弃了许多(但不是全部)Windows 95 / MS-DOS兼容性行李。
如果你希望在进程之间共享数据,正确的方法是通过任何公认的IPC机制 。 一种这样的方法实际上是通过一个内存映射文件,这个文件恰好是一个共享内存块,但是具有访问控制,所以不仅仅是任何进程都可以看到内存。
那么,如果你可以在其他进程的RAM区域搞乱,那么就很容易让它崩溃。 例如,你只需要设置一些指向NULL的指针,这个过程将会消失。 而且RAM是每个进程的“私有”部分,你不想让任何人访问它们吗? 是的,如果你进行一些内核调试,可能有一些方法可以访问。