Windows休眠模式是如何工作的?

5

出于好奇,我在寻找一篇关于“Windows休眠选项如何工作”的文章/文档,即当用户在Windows关闭对话框中选择“休眠”选项时。一些来源给出的回答是,它仅仅是内存和寄存器的序列化。

如果我理解有误,请谅解。如果Windows可以序列化任何应用程序、进程或对象,无论它们是否可序列化,为什么.NET限制可序列化对象只能具有[Serializable]属性或ISerializable接口呢?


1
我不明白.NET框架中的序列化与休眠有什么关系。Windows核心并非使用.NET框架编写的。在这种情况下,序列化并不等同于序列化对象。 - Geo
有些更加平衡的东西,完全不涉及.NET :) - Felice Pollano
据我所知,任何 .NET 对象都可以进行二进制序列化。虽然这与你的问题无关。 - jishi
@jishi - 这要看你的意思是什么... BinaryFormatter 坚持要求 [Serializable]ISerializable; 其他二进制序列化器有不同的要求。但在许多情况下(例如文件句柄),将其序列化没有意义。它无法自行重新创建文件句柄。 - Marc Gravell
我提出这个问题的原因是,尽管.NET被称为托管代码,但仍需要依赖非托管API来执行诸如System.Diagnostics.process.Start()之类的任务,那么如果是这种情况,序列化功能是否也可以共享呢? - AbrahamJP
2个回答

6
在进程地址空间中,一切都是字节;一些堆栈,一些托管堆等。字节本质上是可序列化的 - 它们只是字节。因此,所有的休眠操作都需要做的就是暂停线程并将整个地址空间写入磁盘。
在处理对象方面,您需要将它们保存到一些非内存结构中。不幸的是,存储地址等毫无意义,因为很难通过反序列化恢复到完全相同的内存位置。此外,许多像非托管对象句柄这样的东西在重新加载时也毫无意义。另外,通常情况下,您可能只想保存一个小块的对象,而不是整个进程空间。即使在一个小的图形中,这些对象也可能分散在各处,所以您不能只复制几页内存。
还要注意,序列化的常见用途是对对象进行深度克隆;如果依赖于内存中对象的表示,则必须将其反序列化到完全相同的内存位置 - 因此您无法克隆任何东西。这还没有触及诸如压缩垃圾收集器之类的概念,其可以在您没有看到时移动对象。
还要考虑到您可能将数据加载到不同的平台/架构中,或者想要编写特定格式(xml、json等)。
因此,序列化代码必须查看各个对象,遍历引用,并以允许从与原始内存完全无关的源重新启动的方式编写对象图形。这更加困难。

@Marc,(re)Hydrate是什么意思? - Sanjeevakumar Hiremath
因此,序列化比休眠功能更复杂。您提到的平台/架构不可知点是一个有效的观点。 - AbrahamJP
2
@AbrahamJP - 但是如果仅仅将这些数据加载到同一台机器上的不同进程中,或者在稍后的时间点将其重新加载回相同的进程空间中 - 如果它依赖于原始内存,所有这些操作都会失败。 - Marc Gravell
@Marc 谢谢。我试图读懂这个词之间的含义。 - Sanjeevakumar Hiremath
@AbrahamJP - 我从来没有太关注那个;我主要担心的是对象模型等等 ;p - Marc Gravell
显示剩余4条评论

2
这是两个非常不同的东西。Windows随时控制内存中的内容,并直接访问硬件。我想“序列化”是描述它支持休眠的一个词,但这并不是CLR中的概念。
在.NET中,序列化通常由开发人员显式操作。该属性告诉框架,标记有该属性的类型可以流式传输而无需担心状态或行为差异。
从技术上讲,CLR可能会序列化任何东西,毕竟它可以访问每种类型的底层表示,并跟踪每个对象实例。因此,我想你可以在任何给定点“休眠”整个应用程序域;这更接近于Windows所做的事情。

严格来讲,Windows并没有直接访问硬件的能力;它运行在硬件抽象层中,甚至该层可以位于虚拟机内,后者可以是超级监视器或监控程序模式。操作系统和硬件之间存在许多层。 - Marc Gravell
是的,正如你所说,如果一个应用程序完全依赖于.NET类并选择二进制序列化,那么我相信在Windows平台上,可能存在一些API或功能可以共享,以便在不包含地址空间信息的情况下对对象进行序列化。 - AbrahamJP
@Marc - 不过归根结底,内核拥有它所需或想要的所有访问权限。 - kprobst

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