为什么操作系统没有垃圾回收器?

10

我在想这个问题,因为操作系统负责内存管理。为什么编程语言必须实现自己的垃圾回收器?


2
性能原因。 - Ignacio Vazquez-Abrams
5
不,完全不是。 - Gilles 'SO- stop being evil'
这个问题似乎不适合,因为它涉及操作系统设计,而没有提出实际的编程问题。也许http://cs.stackexchange.com是这个问题更好的地方。 - Raymond Chen
4个回答

8
我在想这个问题,因为操作系统不是负责内存管理吗?只有在操作系统分配内存给程序后,程序才会使用自己的内存管理器来决定如何使用它。进一步将内存管理集中在操作系统中存在问题,因为这会使得速度变慢:程序具有不同的内存访问模式,因此给它们所有相同的GC将使程序员更难以使用自定义内存管理模式。例如,不同的语言运行时需要不同的垃圾收集器以高效地支持语言习惯用法。这也会通过要求操作系统在程序中管理内存来使操作系统设计变得复杂。实际上,在某种意义上,操作系统已经提供了GC:当程序退出时,典型的操作系统会清理其内存。但只要程序在运行,它就要负责管理操作系统给它的内存。
编辑:其他答案中有关于什么构成操作系统的讨论。我考虑了一个狭义的定义,其中操作系统是一个内核,是一个正在运行的程序,提供进程调度和服务。这符合您典型的Windows / Linux / Unix桌面/服务器操作系统。

3
不仅仅是性能问题。通用操作系统无法知道特定运行时环境认为何为引用。 - Gilles 'SO- stop being evil'
1
@Gilles:这只是在语言运行时提供适当的钩子的问题。 - Ignacio Vazquez-Abrams
1
@IgnacioVazquez-Abrams 这就像说解决交通堵塞只是“简单地”发明传送技术一样。许多编程语言不容易进行垃圾回收,它们没有提供连接的位置。 - Gilles 'SO- stop being evil'
3
几乎所有提供内存分配方式的编程语言都会提供一种释放内存的方式。即使是 C 语言也有 free() 函数,虽然该语言不支持自动垃圾回收(GC),但它仍可以使用操作系统强制实施的 GC 功能。 - Ignacio Vazquez-Abrams

8
操作系统如何知道哪些是垃圾,哪些不是?
每种编程语言都有其规则来定义什么是数据结构以及何时另一个数据结构引用了该数据结构。每个编程语言实现(即编译器、解释器、运行时)都有其在内存中表示数据结构的方式。垃圾收集器需要知道数据的表示方式:它需要知道什么是指针,指针指向什么。
通常,指针是内存中的地址。但是没有办法预先知道哪些内存单元包含指针,哪些内存单元包含一些非指针数据,这些数据恰好具有正确的比特模式以成为有效的指针。此外,还需要其他信息才能知道指针引用的数据的大小。
有一些保守型垃圾收集器,它们假定可以将每个可以解释为指针的内存单元视为指针。即使如此,垃圾收集器也需要知道指针所指向的数据从哪里开始和停止,因此垃圾收集器需要了解编程语言环境使用的内存表示。此外,垃圾收集器必须假设不存在隐藏的指针(例如,写入磁盘、压缩等)。
如果程序允许包含任意的机器代码(这是大多数操作系统的情况),则垃圾收集必须留给每个编程环境来完成。有一些专门的操作系统强制所有程序使用相同的运行时环境(例如,所有程序必须在JVM或.NET中运行),并包含垃圾收集器。
操作系统通常包括基于引用计数的特殊形式的垃圾收集器,例如当打开文件的进程数降至0时关闭文件,或者对于共享内存区域也是如此。

4
没有证据,没有相关资源链接和误导性答案的话会被打上“-1”的标记。Microsoft Windows DCOM 是操作系统提供的分布式引用计数垃圾收集器。请参阅Wikipedia: Distributed Component Object ModelWindows → Dev Center - Desktop → The Component Object Model → Managing Memory Allocation - xmojmr
3
DCOM仅为DCOM对象提供垃圾回收,而不是一般数据。 - Gilles 'SO- stop being evil'
4
COM是一个跨平台的、分布式的、面向对象的系统,用于创建可以交互的二进制软件组件。任何一般的数据都可以轻松地被封装并插入到COM生态系统中。许多面向对象编程语言可以与其接口(本地支持)。这里提供了一个用普通C编写的示例:http://www.codeproject.com/Articles/13601/COM-in-plain-C。原帖没有询问“一般数据”,而是询问“操作系统提供的垃圾回收器”。你所说的操作系统无法管理它的观点,因为它不知道这个或那个...在我看来是无效的。 - xmojmr
4
@xmojmr 是的,你可以将所有数据包装成可垃圾回收的框架。我在倒数第二段提到了一些所有数据都被包装的环境示例。像Windows这样的通用平台并不会强制要求程序使用COM或类似的框架,这就是为什么它们无法提供通用GC的原因。它们当然可以为使用COM的程序子集提供GC。 - Gilles 'SO- stop being evil'

4

是的。

垃圾回收需要操作系统知道什么是垃圾,什么不是垃圾,最简单的方法就是某种类型安全保证。一些实验性的操作系统,例如EsSingularity,在内核级别提供类型安全的语言运行时:Es中使用JavaScript,Singularity中使用C#变体。但大多数内核都设计为允许在流行的类型不安全语言(例如C++)中运行应用程序。在这种情况下,内核所能做的就是回收已终止进程占用的内存。

因此,大多数内核将属于特定进程的内存管理委托给语言运行时。所有主要桌面操作系统的默认安装都包括多个垃圾收集语言运行时,可以在其中运行应用程序。

  • .NET Framework自带所有支持的Windows桌面版本。
  • Python自带OS X和流行的GNU/Linux发行版。
  • Android包含Dalvik VM,该VM实现了与Java相同的垃圾回收功能。
  • 此外,所有桌面和移动操作系统都配备了一个实现JavaScript的Web浏览器。

3
这些都不是操作系统级别的。 - Ignacio Vazquez-Abrams
4
对于操作系统(OS)等同于内核(kernel),你是正确的。但并非每个人都同意操作系统等同于内核。你使用了哪个被广泛接受的“操作系统级别”定义? - Damian Yerrick
1
超出语言运行时的范畴。是的,每个运行时都有垃圾回收机制,但它们是独立且不同的垃圾回收机制。 - Ignacio Vazquez-Abrams
2
为什么要定义操作系统以排除随操作系统一起提供的不同语言运行时? - Damian Yerrick

0

垃圾回收将由我们自己的软件处理,在编写软件的过程中,这是很复杂的,并需要开发人员具有先进的经验。

通常,用C和C ++编写的程序不像用Java或PHP编写的程序那样具有自动内存管理。这意味着用C++编写的程序需要程序员定义当不再使用时,软件使用的数据将从内存中删除。

因此,您使用的许多程序都是使用C和C ++编写的,并且在大多数情况下,内存管理并不十分高效。当运行这些程序时,您的内存将包含许多不再使用的碎片,这是程序的失败。我所知道的唯一替代方案是重新启动计算机。

我认为操作系统本身应该有一些工具来“清理未使用的内存空间”,就像Android一样(例如Ccleaner)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接