TONT 38363 为什么有些进程在被中止后,仍然在进程管理器中显示着?

原文链接:https://devblogs.microsoft.com/oldnewthing/20040723-00/?p=38363

When a process ends (either of natural causes or due to something harsher like TerminateProcess), the user-mode part of the process is thrown away. But the kernel-mode part can’t go away until all drivers are finished with the thread, too.

当一个进程被中止时(不论是通过比较自然的方式,还是比较严厉的如 TerminateProcess(译注:原文链接已失效,此处为MSDN上对应的文章目前可用的链接) 的方式),其用户模式下的部分就被抛弃了,不过其内核部分在线程中的所有驱动结束操作前,是无法被移除的。

For example, if a thread was in the middle of an I/O operation, the kernel signals to the driver responsible for the I/O that the operation should be cancelled. If the driver is well-behaved, it cleans up the bookkeeping for the incomplete I/O and releases the thread.

例如,如果某个线程正处在一个 I/O 操作中,内核将通知该 I/O 操作对应的驱动取消该操作。倘若这个驱动运作正常的话,就应当对这个未完成的 I/O 操作进行清理,并最终释放对应的线程。

If the driver is not as well-behaved (or if the hardware that the driver is managing is acting up), it may take a long time for it to clean up the incomplete I/O. During that time, the driver holds that thread (and therefore the process that the thread belongs to) hostage.

但如果驱动运作不正常(或其所管辖的硬件出现了问题),可能就需要比较长的时间来清理这个未完成的 I/O 操作。在此期间,该驱动将持续保有相应的线程(该线程所属的进程亦然)。

(This is a simplification of what actually goes on. Commenter Skywing gave a more precise explanation, for those who like more precise explanations.)

(这是对类似事情发生时的情况的一个简化描述,访客 Skywing 撰写了一份更加准确的描述(译注:链接已失效,我们永远都无法再知道那天dalao说了些什么了),喜欢细节描述的人可以去看看。)

If you think your problem is a wedged driver, you can drop into the kernel debugger, find the process that is stuck and look at its threads to see why they aren’t exiting. You can use the !irp debugger command to view any pending IRPs to see what device is not completing.

如果你认为问题出在某个加楔而入的驱动上,你可以打开内核调试器,找到那个(关不掉的)进程,检视其线程列表来判断为什么它不肯退出,也可以在调试器中使用 !irp 命令来观察处于等待状态下的 IRP(译注:I/O Request Package,I/O 请求包),并由此判断是哪个设备没有完成其操作。

After all the drivers have acknowledged the death of the process, the “meat” of the process finally goes away. All that remains is the “process object”, which lingers until all handles to the process and all the threads in the process have been closed. (You did remember to CloseHandle the handles returned in the PROCESS_INFORMATION structure that you passed to the CreateProcess function, didn’t you?)

当所有的驱动得知某进程被中止的情况后,该进程的『肉体』才终于消失,而剩下的只是一个『进程对象』继续等待着,直到所有面向该进程的句柄及进程的所有线程都关闭位置。(你应该有记得把在调用 CreateProcess 时在 PROCESS_INFORMATION 结构中返回的句柄们用 CloseHandle 都关掉来着(译注:原文链接已失效,此处为目前MSDN上的新链接),没错吧?)

In other words, if a process hangs around after you’ve terminated it, it’s really dead, but its remnants will remain in the system until all drivers have cleaned up their process bookkeeping, and all open handles to the process have been closed.

换句话说,如果某个进程在被中止后仍然挂在那里,实际上这个进程的确已经被中止了,只是还有点小『残余』留在了系统中,直到所有相关的驱动完成了针对这个进程的清理工作,以及所有由该进程打开的句柄被关闭为止。

TONT 38373 为什么你不能捕获TerminateProcess?

原文链接:https://devblogs.microsoft.com/oldnewthing/20040722-00/?p=38373

If a user fires up Task Manager and clicks “End Task” on your program, Windows first tries to shut down your program nicely, by sending WM_CLOSE messages to GUI programs and CTRL_CLOSE_EVENT events to console programs. But you don’t get a chance to intercept TerminateProcess. Why not?

如果用户打开任务管理器,选中你的程序之后点击『结束任务』,Windows将首先尝试优雅地通知你的程序进行关闭,方法是向GUI应用发送WM_CLOSE消息,或者向控制台应用发送CTRL_CLOSE_EVENT事件。不过,你是不可能拦截 TerminateProcess 的。这是为什么呢?

TerminateProcess is the low-level process killing function. It bypasses DLL_PROCESS_DETACH and anything else in the process. Once you kill with TerminateProcess, no more user-mode code will run in that process. It’s gone. Do not pass go. Do not collect $200.

TerminateProcess(译注:原文链接已失效,此处为MSDN上对应的新链接)是一种底层结束任务的方法,可以绕过 DLL_PROCESS_DETACH 及进程中的任何东西。一旦调用 TerminateProcess 来结束进程的话,该进程中将不再有任何用户模式的代码可以运行。就那么结束了。别再想着过起点了,也别再想挣200块的事了。(译注:Do not pass go. Do not collect $200是原版“大富翁”游戏中直接将其它玩家送入监狱格的事件卡片背面文字,用于强调“啥也别想了,没救了”的意思。)

If you could intercept TerminateProcess, then you would be escalating the arms race between programs and users. Suppose you could intercept it. Well, then if you wanted to make your program unkillable, you would just hang in your TerminateProcess handler!

假设有办法拦截 TerminateProcess 的话,不过是恶化了程序和用户之间的军备竞赛而已。设想如果可以拦截它,那么,如果想让你的程序无法被中止,只要在你的 TerminateProcess 处理进程中挂起就好啦!

And then people would ask for “a way to kill a process that is refusing to be killed with TerminateProcess,” and we’d be back to where we started.

然后就会有人提出『如何中止拒绝被 TerminateProcess 杀掉的进程』这样的问题,于是我们又回到了问题的开头。

TONT 38383 为什么Windows 98下的最大显示器数量是9?

原文链接:https://devblogs.microsoft.com/oldnewthing/20040721-00/?p=38383

Windows 98 was the first version of Windows to support multiple monitors. And the limit was nine.

Windows 98是支持多显示器的第一个Windows版本,而显示器数量的上限是9。

Why nine?

为什么是9呢?

Because that allowed you to arrange your monitors like this. You have early seventies television to thank.

因为这个数字允许你将显示器的排列摆成这样(译注:即3×3的显示器阵列,类似老式高档电视中的多频道预览功能)。这一点你得感谢70年代早期的电视设计。

TONT 38463 留心那些示例URL们

原文链接:https://devblogs.microsoft.com/oldnewthing/20040713-00/?p=38463

When writing documentation, one often has need to come up with a sample URL to illustrate some point or other. When you do, make sure the sample URL is under your control.

撰写文档时,有时需要一个示例 URL 来描述一些论点之类的东西,遇到这种情况时,留心让那些示例 URL 在你的掌控之下。

I remember a Windows beta that used the sample URL http://www.xxxxx.com/ in a dialog box. You can imagine where that actually goes.

我记得有一个 Beta 版的 Windows 在某个对话框中使用了 http://www.xxxxx.com/ 作为示例URL,可想而知这个网址指向的是什么地方。

This web site uses www.wallyworld.com as a sample URL. Perhaps they didn’t realize that it’s a gay porn site.

这个网站(译注:链接已失效)使用了 www.wallyworld.com 作为示例 URL,估计他们没想到这个网址是一个同性恋色情网站。

(Raymond’s strange dream story: One night I dreamt that I found a web site that had a complete Dilbert archive, and for some reason the name of the site was “Wally World”. In the morning, I checked out the site and was in for a big surprise…)

(Raymond 的怪梦小故事:某晚我做了一个梦,梦见有个网站上有 Dilbert 漫画的全集存档,并且不知为何网站的名字叫 Wally World。第二天早上,我搜了一下这个网站,结果非常令人“惊喜”。)

So play it safe. When you need a sample URL, don’t just make something up. If you do, odds are good that somebody is going to rush in and register it. Make your sample URLs point back to your company’s home page, or use http://www.example.com, which the IANA has reserved for use in sample URLs. If that’s too dorky, you can always go out and register the domain you want to use as your sample, so that nobody else can sneak in and steal it. (This does have the problem of incurring renewal fees.)

所以还是小心为妙。当需要用到示例 URL 时,不要随手编一个就算了,总有人会立马跑去把这个域名注册下来。你可以让这个示例 URL 跳转回贵公司的主页,或者直接用 http://www.example.com ,这是 IANA 为示例 URL 保留的一个域名。如果你觉得这样太傻了,你当然也可以选择(先)特意注册一个域名,然后将它用在你的示例 URL 之中,这样就不会有人悄悄地将其据为己有了。(不过这样也会有为其续费的问题存在。)

TONT 38493 『添加/删除程序』是如何获知应用程序的大小等信息的?

原文链接:https://devblogs.microsoft.com/oldnewthing/20040709-00/?p=38493

If the program doesn’t provide this information itself, Add/Remove Programs is forced to guess.

如果应用程序没有主动提供这些信息,『添加/删除程序』不得已就得用猜的了。

The problem is that there is no “obvious” way to map an entry in the Add/Remove Programs list to an actual program. Each entry in the list, for those who care about such things, comes from the HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall registry key. The only mandatory properties for an uninstallable program are the DisplayName and the UninstallPath. Everything else is optional.

问题在于,『添加/删除程序』并没有一种明确的手段将一项(已安装程序的)条目与实际的应用程序关联起来。为关注相关事项的人服务一把:(『添加/删除程序』中的)每一个条目都取自注册表键 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall。对于每个可以卸载的应用程序而言,必需的条目是 DisplayName 和 UninstallPath,剩下的都是可选项。

Let’s suppose Add/Remove Programs is given a program registration like this:

假设有以下注册表信息被给予了『添加/删除程序』:

HKEY_LOCAL_MACHINE\
Software\
Microsoft\
Windows\
CurrentVersion\
Uninstall\
SomeProgram
DisplayName=REG_SZ:”Awesome Program for Windows”
UninstallPath=REG_SZ:”C:\WINDOWS\uninstall.exe -SomeParameters”

In order to get the “Last Used” and “Frequency” values, Add/Remove Programs needs to know the name of the EXE so it can ask the Start menu “Hey, how often did the user run this program, and when was the last time it happened?”

为了获取『最近使用时间』和『使用频率』的值,『添加/删除程序』需要知道应用程序主程序的EXE文件名,这样才能向开始菜单咨询:『嗨,用户有多经常运行这个应用程序,上次运行又是什么时候的事情呀?』

Notice that there are no clues in the registration above as to the identity of this EXE file.

请注意,上述注册表信息中,并无辨认应用程序主程序EXE文件的线索。

So Add/Remove Programs starts guessing. It goes through all the programs on your Start menu and compares their names with the display name of the uninstallable item. It looks for Start menu items which share at least two words with the words in the DisplayName.

于是『添加/删除程序』就开始靠猜的了。『添加/删除程序』遍历开始菜单,将上述注册表信息提供的、可卸载应用程序的『显示名称』与开始菜单中的条目进行比较,标准是有至少两个单词与 DisplayName 相同。

For example, if there were a Start menu item called “Pretty Decent Windows Program”, this would count as a two-word match (“Windows” and “Program”).

例如,如果有一个开始菜单条目叫『Pretty Decent Windows Program』,这样就算有两个单词相符(Windows 和 Program)(译注:前例中的 DisplayName 叫 Awesome Program for Windows)了。

It then takes the one with the most matches and decides, “Okay, I guess this is it.” Suppose for the sake of illustration that the best match is indeed “Pretty Decent Windows Program.lnk”, which is a shortcut to “C:\Program Files\LitWare\Decent Program\Decent.exe”. Add/Remove Programs would decide that “Awesome Program for Windows” should get the icon for “Pretty Decent Windows Program.lnk”, that the frequency of use and most-recently-used information for “C:\Program Files\LitWare\Decent Program\Decent.exe” will be displayed for “Awesome Program for Windows”.

『添加/删除程序』会挑选相似程度最高的一项,然后下定决心说:『行了,依我看就是它了。』假设在本例中,相似程度最高的一项正好是『Pretty Decent Windows Program.lnk』,而它是到『C:\Program Files\LitWare\Decent Program\Decent.exe』的快捷方式,『添加/删除程序』便由此决定『Awesome Program for Windows』应当采用『Pretty Decent Windows Program.lnk』的图标,而使用频率和最近使用时间的信息则取自『C:\Program Files\LitWare\Decent Program\Decent.exe』。

But wait, there’s more. There’s also the program size. Add/Remove Programs looks in your “Program Files” directory for directories whose names share at least two words in common with the DisplayName. The best match is assumed to be the directory that the program files are installed into. The sizes are added together and reported as the size of “Awesome Program for Windows”.

不过等等,还没完。还有一项信息叫『大小』。『添加/删除程序』将在『Program Files』目录中查找与 DisplayName 有至少两个单词相同的项目,而该项目则被视为应用程序的安装目录。将这个目录下的文件大小汇总一下,这个数字就作为『Awesome Program for Windows』的『大小』了。

A program can add some properties to its registration to avoid a lot of this guessing. It can set an EstimatedSize property to avoid making Add/Remove Programs guess how big the program is. It can also set a DisplayIcon property to specify which icon to show for the program in the list.

应用程序可以在向注册表中写入信息时主动指定对应的属性值来避免上述的猜测工作,比如可以通过设置 EstimatedSize 属性来省去『添加/删除程序』估算应用程序的大小,也可以通过设置 DisplayIcon 来指定在列表中应用程序的图标。

But if a program omits all of these hints, the guess that Add/Remove Programs ends up making can often be ridiculously wide of the mark due to coincidental word matches. In my experience, Spanish suffers particularly badly from this algorithm, due to that language’s heavy use of prepositions and articles (which result in a lot of false matches).

不过,如果某个应用程序完全无视这些提示的话,『添加/删除程序』估测出来的信息有可能因为巧合的单词相符而与实际情况大相径庭。据我个人经验而言,西班牙语(的条目)在面对这一算法时误差最大,原因是西班牙语中的介词和冠词的使用极其频繁(因而造成了大量的误匹配)。

Yes, this is all lame, but when you are forced to operate with inadequate information, lame is the best you can do.

没错,这个机制是很蹩脚,但当你被迫用不完整的信息来构建资料时,做到蹩脚已是最好的结果。

[July 15 2004: Emphasizing that this is done only if the program fails to provide the information itself. For some reason, a lot of people who link to this page fail to notice that little detail.]

(2004年7月15日更新:强调一下,『添加/删除程序』只有在应用程序未能提供相关信息时才会进行上述的猜测工作。不知为何,很多链接到这个页面的读者都忽略了这一细节。)

TONT 38513 关闭阴影效果时,为什么图标下的文字会有一个纯色色块?

原文链接:https://devblogs.microsoft.com/oldnewthing/20040708-00/?p=38513

A commenter asks why icon label have “those ugly color boxes” when there is a background image.

有位访客在评论中提问为什么当设置了背景图片时,图标标签下面会有『难看的色块』。

The answer: Because the alternative would be worse.

答:因为不这样的话更难看。

Imagine if there were no solid background between the text and the background image. You would end up with text against an unpredictable background, which doesn’t help readability.

试想,如果在文本和背景图片之间没有纯色背景衬托的话,结果就变成文本压在了无法预测的背景图片上的情况,对可读性并无益处。

Take the default background for Windows XP: There are some places that are very light and other places that are very dark. No matter what color you pick for the icon text, it will look bad in one or the other place. If you decide to use white, then the text becomes unreadable in the clouds. If you decide to use black, then the text becomes unreadable in the shadows.

以 Windows XP 的默认背景(译注:Bliss,即经典的蓝天白云绿草地)为例:图片上的某些部分特别亮,有些则特别暗。不论你选择哪种(单一)颜色作为图标标签文字的颜色,都可能在一处或者另一处看上去很难看。用白色,那么在白云部分文字就很难看清,而用黑色的话,在阴影部分又看不见了。

You lose either way.

怎么样都是输。

The solution is to intercede a contrasting color to ensure that the text is readable. If your video card is powerful enough, the contrasting color is used only just around the strokes of text themselves, which lends a shadow-effect. If shadows are not enabled, then a solid block of contrast is used.

解决方案是引入高对比度的颜色从中斡旋,以确保文本的高可读性。如果你的显卡性能足够强,这个高对比度的颜色只会在文字的边缘轻轻一描,形成一种阴影效果。而如果阴影效果没有启用的话,那么就会在文字下方描绘一个纯色色块。

(And for those of you who say, “Use white in the dark places and black in the light places,” what if there is a section of the wallpaper that has a dark area right next to a light area, and the text covers both?)

(至于那些准备说『在深色区域用白色,在浅色区域用深色』的那些人,如果(用户的)壁纸上正好有一块深浅相间的区域,而图标标签的文本正好横亘其上呢?)

TONT 102300 (38583) 不要把你的DLL命名为Security.dll

题外话:

鉴于 The old new thing 博客迁移至 Microsoft Developer Blogs 之后,部分文章 ID 发生了彻底变化(毫不相关),故自本篇起,存在该问题的对应博文,如在本人手中具有旧版备份,则会在标题中以括号的形式标出旧 ID,新 ID 则在其之前,以不带括号的形式提供。如遇文章的新、旧 ID 相同,或可以通过旧 ID 直接在新版 The old new thing 上进行访问,则只会撰写一个 ID。

原文链接:https://devblogs.microsoft.com/oldnewthing/20040702-00/?p=102300

Reaching back into the history bucket…

让我们回到历史的故纸堆中。

Some people have discovered that strange things happen if you name your DLL “security.dll”.

有人发现,如果将你(开发)的 DLL 命名为 security.dll,就会发生一些奇怪的事情。

The reason is that there is already a system DLL called “security.dll”; it’s the Security Support Provider Interface DLL, and it used to go by the name “security.dll”, though nowadays the name “secur32.dll” is preferred. If you look into your system32 directory, you’ll see both “security.dll” and “secur32.dll” in there. And if you’re handy with an export dumper, you’ll see that “security.dll” is just a bunch of forwarders to “secur32.dll”. If you browse through the MSDN documentation, you’ll see that everybody talks about “secur32.dll” and hardly any mention is made of its doppelgänger “security.dll”.

这是由于已经有一个系统 DLL 的名字叫 security.dll 了,它是(系统的)安全支持提供器接口(SSPI)的 DLL,并且曾经用过  security.dll 的名字,虽然如今比较推荐使用 secur32.dll 就是了。打开你的 system32 目录的话,你会同时看到 secutiry.dll 和 secur32.dll,如果手头上正好有DLL导出函数浏览器的话,你会发现 security.dll 的导出函数不过是一大堆到 secur32.dll 的转发而已。另外,浏览一下 MSDN 文档,也会发现大多数文章里提及的都是 secur32.dll,而极少提及它的影子弟兄 security.dll。

Okay, here’s where the history comes in. Wind back to Windows 95.

好了,现在让我们来谈谈历史,首先回到 Windows 95 的年代。

Back in those days, the Security Support Provider Interface was implemented in two different DLLs. The one you wanted depended on whether you are running Windows NT or Windows 95. On Windows 95, it was called “secur32.dll”, but on Windows NT, it was called “security.dll”.

从前,SSPI 是通过两个不同的 DLL 实现的,需要使用哪一个取决于是在运行 Windows NT 还是 Windows 95。在 Windows 95 里,SSPI 的 DLL 叫 secur32.dll,但在 Windows NT 中,则叫 security.dll。

This was obviously a messed-up state of affairs, so the Windows NT folks decided to “go with the flow” and rename their security DLL to “secur32.dll”. This was probably for application compatibility reasons: Applications that were written to run on Windows 95 and were never tested on Windows NT just went straight for “secur32.dll” instead of loading the correct DLL based on the operating system.

很明显,这样的安排简直是一团糟,所以 Windows NT 开发组的老哥们决定『随波逐流』,将他们的安全 DLL 改名成了 secur32.dll。这大概是出于对应用程序兼容性的考量:面向 Windows 95 开发、并且从来没有在 Windows NT 上测试过的的应用程序会直奔 secur32.dll 而去,而不会根据操作系统的情况去选择加载正确的 DLL。

Okay, so now pop back to the present day. When you put a DLL called “Security.dll” in your application directory, what happens?

好了,回到现在。当你将一个叫 security.dll 的 DLL 放在你的应用程序目录中,会发生什么呢?

Recall that the rules for the order in which DLLs are searched for checks the application directory before it checks the system directory. As a result, anybody in your application who wants “Security.dll” will get your version instead of the system version.

回忆一下有关 DLL 的搜索顺序的设定(译注:原链接已失效,中文链接为新地址),Windows 会在去系统目录下查找之前,先在应用程序的工作目录下进行搜索。因此,由你的应用程序发起的调用,如果要查找名叫 security.dll 的 DLL,都会拿到你(放在应用程序目录下)的版本,而不是系统(目录)中的版本。

Even if the system version is the one they really wanted.

即便系统目录中的那个版本是它们真正需要的。

That’s why overriding the system’s Security.dll with your own results in a bunch of SSPI errors. Components you are using in your program are trying to talk to SPPI by loading “security.dll” and instead of getting the system one, they get yours. But yours was never meant to be a replacement for “security.dll”; it’s just some random DLL that happens to have the same name.

这就是为什么以你自己版本的 security.dll 替代系统版本会引发一大堆 SSPI 相关的错误。你的应用程序中的组件尝试进行 SSPI 调用时会去尝试加载 security.dll,而基于以上规则,组件会拿到你的程序目录下的版本,而不是系统目录中的版本。然而你的 security.dll 并不是系统中那个 security.dll 的替代品,只是一个恰好同名的、其它用途的 DLL 而已。

You would have had the same problem if you happened to name your DLL something like “DDRAW.DLL” and some component in your program tried to create a DirectDraw surface. “Security.dll” has the disadvantage that it has a simple name (which people are likely to want to name their own DLL), and its importance to proper system functionality is not well-known. (Whereas it would be more obvious that creating a DLL called “kernel32.dll” and putting it in your application directory is going to cause nothing but trouble.)

同样地,当你的 DLL 碰巧起了个名字叫 ddraw.dll 而你的程序中某个组件尝试创建 DirectDraw 绘图平面时,也会发生类似的问题。Security.dll 的劣势在于其名称太简明了(因而人们可能会把他们的 DLL 起一个相同的名字),并且其对系统运行的重要性并非广为人知。(然而更明显的是创建一个 DLL 起名叫 kernel32.dll 然后放进你的应用程序目录中,那么除了麻烦之外什么也不会产生。)

(译注:事实上 kernel32.dll 由于属于 KnownDLLs(注册表 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs),Windows 会仅在系统目录中查找在该列表中的DLL 而不遵守前述的规则,所以并不会发生这个问题,而 security.dll 之所以至今有这个问题,个人认为更多的还是由于首先微软在历史上搞砸了这个文件的命名,然后又替水平参差不齐的软件开发商背了一部分的黑锅)

Day 4988 关于本博客『Win故知新』分类恢复更新的说明

对 Raymond Chen 的博客《The old new thing》(下文简称TONT)的随缘翻译停了几个月,起因是大约在今年(2019年)5月份时(相关博文原文链接),TONT 整体迁移到了 Microsoft Developer Blog平台,该平台较之旧版对移动端友好,但由于需要遵守欧盟缺德数据保护条例(GDPR),所有的评论都被丢弃了。由于某些文中未完整解明的问题,评论区有人提问后,Raymond 可能在回复中给予进一步解释,故对评论的丢弃实为一大损失。

虽然微软在推特账号 MSDN Services Status(@MSDNService)上声明,为便于用户通过搜索(引擎?)查找已经不再活跃更新的MSDN Blog、TechNet Blog上的数据,将对这些博客进行静态化处理,然而对于一直都在更新的 TONT 来说显然不在此列,而后面几个月以来的实际情况也证实了这一点。

发现该情况后,虽感觉希望渺茫,本人仍然尝试了许多方法去访问旧版的 TONT 内容。在经历了不下数十次碰壁后,发现可能是由于 CDN 缓存的原因,每20-30次访问之间偶尔可以进入旧版页面,同时,该现象还具有如果访问结果是跳转新版页面,则在 HTTP 状态码为 301 的同时内容为空的特点。由此,本人编写了一个简单的下载程序,通过导入 URL 列表的方式,对每个页面最多访问一万次(两次访问间有2-5秒的随机间隔),试图拉取到旧版内容。

程序自2019年5月31日上线,经过一个多月的7×24连续运行,至7月3日起,连续一个星期没有再拉取到新的内容,基本判定该 bug 已被修复,于是停止了下载程序的运行。期间,共成功下载到 TONT 的 1804 篇旧版博客内容,包含对应文章的完整评论。该部分内容不会放出下载,以避免不必要的麻烦。

即日起,『Win故知新』栏目恢复更新,更新频率仍为随缘。

Day 4849 自行组装RAID10磁盘阵列

以前的时候,由于家里的网速一直不是很快,加上由于环境受限,一直没有外网环境,从来没有做过资源党,也就对硬盘空间没有多高的需求。事实上,从第一台电脑开始,家中的台式机几乎一一直是单(机械)硬盘配置,依次经历了2G、20G、120G、600G、1T和2T的容量台阶,并且在600G以前一直是IDE接口。

然而对存储空间的追求是永无止境的,为了在一段时间内暂时不再受台式机硬盘的限制,又忌惮于群晖的价格,一狠心,实践了一次用阵列卡自行组装磁盘阵列的想法。

这中间也算学到了点东西。

继续阅读 “Day 4849 自行组装RAID10磁盘阵列”