【问题标题】:Why doesn't the OS have a garbage collector?为什么操作系统没有垃圾收集器?
【发布时间】:2014-12-07 04:16:19
【问题描述】:

我对此感到疑惑,因为操作系统负责内存管理。为什么编程语言必须实现自己的垃圾收集器?

【问题讨论】:

  • 性能原因。
  • @IgnacioVazquez-Abrams 不,一点也不。
  • 这个问题似乎离题了,因为它是关于操作系统设计的,并且没有提出实际的编程问题。也许cs.stackexchange.com 会是这个问题更好的地方。

标签: memory-management garbage-collection operating-system programming-languages


【解决方案1】:

垃圾收集将由自己的软件,在软件的编程或编码中进行,但这很复杂,需要开发人员的高级经验。

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

因此,您使用的许多程序都是用 C 和 C++ 编写的,并且在大多数情况下内存管理效率不是很高。当运行这些程序时,您的内存将包含许多不再使用的片段,这是程序的失败。我知道的唯一选择是重启电脑。

我同意 SO 本身应该有一些工具来“清理未使用的内存空间”,就像它在 Android 上一样(例如 Ccleaner)。

【讨论】:

    【解决方案2】:

    我想知道这是因为操作系统不负责内存管理吗?

    仅在操作系统将内存分配给程序的意义上,然后程序决定如何使用自己的内存管理器来使用它。在操作系统中进一步集中内存管理是有问题的,因为它会很慢:程序有不同的内存访问模式,因此给它们所有相同的 GC 将使程序员更难使用自定义内存管理模式。例如,不同的语言运行时需要不同的垃圾收集器以有效的方式支持语言的习惯用法。它还要求操作系统管理程序中的内存,从而使操作系统设计复杂化。

    实际上,在某种意义上,操作系统已经提供了GC:当程序退出时,典型的操作系统会清理它的内存。但只要程序在运行,它就负责管理操作系统给它的内存。

    编辑:其他答案中有一些关于什么构成操作系统的讨论。我考虑了一个狭义的定义,其中操作系统是一个内核,一个为进程提供调度和服务的运行程序。这与您的典型 Windows/Linux/Unix 桌面/服务器操作系统相匹配。

    【讨论】:

    • 这不仅仅是性能问题。通才操作系统无法知道特定运行时环境认为什么是参考。
    • @Gilles:这只是在语言运行时提供适当的钩子的问题。
    • @IgnacioVazquez-Abrams 这就像说解决交通拥堵“只是”发明隐形传输的问题。许多语言不允许垃圾收集,它们没有提供连接的地方。
    • @Gilles:几乎所有提供分配内存的方法的语言也提供了释放内存的方法。甚至 C 也有 free(),尽管该语言不支持 GC,但它仍然允许它使用 OS 强制的 GC 工具。
    【解决方案3】:

    操作系统如何知道什么是垃圾,什么不是?

    每种编程语言都有自己的规则来定义数据结构是什么,以及数据结构何时被另一个数据结构引用。每种编程语言实现(即编译器、解释器、运行时)都有其在内存中表示数据结构的方式。垃圾收集器需要知道数据是如何表示的:它需要知道什么是指针,指针指向什么。

    通常,指针是内存中的地址。但是没有办法先验地知道哪些存储单元包含指针,哪些存储单元包含一些非指针数据,这些数据恰好具有正确的位模式作为有效指针。此外,还需要额外的信息来了解指针所引用的数据的大小。

    有一些保守的垃圾收集器,它们假设每个可以被解释为指针的内存单元都是一个指针。即使这样,垃圾收集器也需要知道指针指向的数据在哪里开始和停止,因此垃圾收集器需要知道编程语言环境使用的内存表示。此外,垃圾收集器必须假设没有隐藏指针(例如,写入磁盘、压缩……)。

    如果允许程序包含任意机器代码(大多数操作系统都是这种情况),那么垃圾收集必须留给每个编程环境。有一些专门的操作系统会强制所有程序使用相同的运行时环境(例如,所有程序都必须在 JVM 或 .NET 中运行)并且确实包含垃圾收集器。

    操作系统通常包含特殊形式的垃圾收集器,通常基于引用计数,例如,当打开文件的进程数降至 0 时关闭文件,或者对于共享内存区域也是如此。

    【讨论】:

    • -1 没有证据,没有相关资源的链接和误导性答案。 Microsoft Windows DCOM 是 OS 提供的分布式引用计数垃圾收集器。见Wikipedia: Distributed Component Object ModelWindows → Dev Center - Desktop → The Component Object Model → Managing Memory Allocation
    • @xmojmr DCOM 只为 DCOM 对象提供 GC,不为一般数据提供 GC。
    • “COM 是一个独立于平台、分布式、面向对象的系统,用于创建可以交互的二进制软件组件”。任何通用数据都可以(轻松)打包并插入 COM 生态系统。许多 OO 编程语言可以(本地)接口它。此处提供了纯 C 示例:codeproject.com/Articles/13601/COM-in-plain-C。 OP 没有询问“一般数据”,OP 询问了“操作系统提供的垃圾收集器”。您认为操作系统无法管理它的观点是因为它不知道这个或那个..是无效的(IMO)
    • @xmojmr 是的,您可以将所有数据包装到可垃圾收集的框架中。我提到了一些环境示例,其中所有数据都包含在我的倒数第二段中。 Windows 等通用平台不会强制程序使用 COM 或类似框架,这就是它们无法提供通用 GC 的原因。他们当然可以为使用 COM 的程序子集提供 GC。
    【解决方案4】:

    确实如此。

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

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

    • .NET Framework 附带所有受支持的 Windows 桌面版本。
    • Python 随 OS X 和流行的 GNU/Linux 发行版一起提供。
    • Android 包含 Dalvik VM,它实现与 Java 相同的垃圾收集。
    • 此外,所有桌面和移动操作系统都附带实现 JavaScript 的网络浏览器。

    【讨论】:

    • 这些都不是操作系统级别的。
    • @Ignacio 对于 OS == 内核,您是正确的,但并非所有人都同意 OS == 内核。您使用的是哪个被广泛接受的“操作系统级别”定义?
    • 语言运行时之上的那个。是的,这些运行时中的每一个都有一个 GC 设施,但它们是独立且不同的 GC 设施。
    • 为什么要定义操作系统以排除操作系统附带的不同语言运行时?
    猜你喜欢
    • 1970-01-01
    • 2020-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多