因此,我正在与老板讨论一下内存管理。
我听说终止进程并不允许其释放内存。现在还是这样吗,还是几年前就这样了?
我们这里讨论的是 Windows 和 OS X。
答案1
我已经很久没有学过这些东西了,但现在我要开始学习了。
当操作系统启动进程时,它会从虚拟内存表中为其分配页面。操作系统负责维护从虚拟内存表到实际内存或磁盘上的交换空间的映射。当进程被终止时,操作系统不会停止为其提供 CPU 周期。它会执行一些清理操作,其中之一就是将其所有内存页面标记为空闲。这允许其他应用程序重用它们。操作系统可能还会清理进程拥有的任何资源句柄,自动关闭文件、网络连接、进程到进程的管道等。此进程完全由操作系统控制,无论进程如何终止,都会执行这些步骤。
请记住,所有这些都适用于操作系统进程。如果您有某种虚拟机,并且它同时运行多个虚拟进程,那么虚拟机负责决定如何分配和释放它们。但是,从操作系统来看,它仍然看起来像一个进程。因此,在这种情况下,如果您有一个运行多个进程的虚拟机,并且您在虚拟机中终止其中一个进程,那么您可能不会立即在主机操作系统中恢复内存。但您会在虚拟机中恢复它。但是,如果您在操作系统中终止虚拟机,那么操作系统将终止虚拟机(这间接终止了虚拟机的进程)并回收所有内存(无需经过垃圾收集器、free()、delete 或其他任何操作)。
高度推测:
如果 .NET 作为虚拟机运行,并且在同一台虚拟机上有多个 .NET 应用程序,那么 .NET 可以保留尚未 GCd 的内存,直到运行 GC,并且 Windows 会认为 .NET 使用的内存比实际的多。 (如果 MS 真的很聪明,Windows 可以在内存紧张的情况下告诉 .NET 进行 GC,但这几乎没有意义,因为这就是磁盘交换空间的用途。)
如果 .NET 确实以这种方式工作,那么操作系统仍会将其视为一个进程,负责决定保留什么和丢弃什么,并且通常 Windows 不会告诉进程需要开始释放内存。此时,可以想象 MS 会为 .NET 构建一个特殊的 API,以便 .NET 进程看起来像 Windows 进程,但实际上并非如此,这就是为什么人们可能会认为进程内存没有被释放。事实上,确实如此;只是你看错了进程。
我对 .NET 了解不够多,无法说它确实以这种方式工作;Java VM 肯定不是这样。
猜测结束。
编辑:就终止进程不利于内存管理而言,这需要多个进程从同一个池中分配内存(即它们更像是线程而不是真正的进程),并且进程终止后内存不会被释放。这几乎需要一个协作式多任务系统,因为据我所知,虚拟内存和抢占式多任务通常是一起实现的(VM 可以将进程彼此隔离,并防止它们占用彼此的内存)。有了虚拟内存,在操作系统级别上清理进程就变得轻而易举了;您只需将所有页面从进程池移动到空闲池即可。
答案2
以我的经验来说没问题,杀掉就好。
举例来说,如果您有 4 GB 的 RAM,其中 3 GB 正在由游戏使用,而您终止了游戏进程,那么您可以毫无问题地重新启动游戏,并且该进程将再次拥有 3 GB 的 RAM。
答案3
问题标签中列出的操作系统(Windows 和 OS X)实现虚拟内存,其中每个进程都有自己的地址空间,然后由操作系统将其映射到物理内存。这些映射表用于在进程终止时清理内存分配,以便完全释放内存。物理页面可能在多个进程之间共享,在这种情况下,当没有更多用户时,它们将被释放。
通常,文件句柄等其他资源以以下形式提供给进程能力,其中进程接收资源的句柄并通过明确定义的访问函数对其进行操作。操作系统会保留一个表,将句柄值映射到提供该函数的内核对象;同样,当进程终止时,可以使用此表进行清理。
有一些特殊资源在创建它们的进程之后仍会继续存在,例如,可以创建持久命名的共享内存分配,用于进程间通信。这些资源很少使用,正是因为操作系统无法确定它们是否仍然需要。
在其他操作系统中,有时没有明确的进程分离;这将清理的负担放在了各个应用程序上。
强行关闭一个进程将会终止该进程而不给它任何清理的机会;如果操作系统有所有资源的完整列表,这不会产生任何不利影响。
答案4
那是在内存管理尚未广泛实施的时代。如今,您可能错过的唯一内存是驱动程序和内核模块使用的未被杀死或处于僵尸状态的内存,但这真的微不足道。