网易首页 > 网易号 > 正文 申请入驻

微软为什么不用指针,而要多绕一层?

0
分享至


本文来自微信公众号: 宇众不同的露萱 ,作者:宇众不同的露萱

大概是在七八年前,我当时在学习Unix系统的内核代码,特别是open()返回的那个简单至极的整数文件描述符(File Descriptor)。那时候身边不少做Windows开发的朋友,提到系统底层,嘴里永远绕不开一个词:HANDLE。

一个指针大小的32位或64位无符号整数,指向一个在用户态完全看不见的内核对象。

当时我其实有一个很粗暴的偏见:Windows搞出HANDLE,无非就是微软习惯了搞封装、搞抽象,非要把原本简单的整数索引包装成某种看起来很“面向对象”的东西。甚至在很长一段时间里,我都觉得它只是C++时代产物下的某种过度设计。

直到后来我去翻早期微内核与操作系统设计的历史,尤其是阅读Dave Cutler(Windows NT的首席架构师)在VMS和NT时代的设计记录,我才意识到,我以前完全理解错了。

HANDLE不是微软为了秀面向对象抽象而凭空发明出来的。它的出现,本质上是一场关于“谁有权解释内核内存”的死斗。

在1980年代末,Dave Cutler带着一帮DEC的工程师被比尔·盖茨挖到微软开荒Windows NT时,他们面临的硬件环境和设计目标,和Linus Torvalds后来写Linux时有着微妙但决定性的不同。

当时的Unix哲学非常优雅,“一切皆文件”。你打开一个文件,系统给你一个fd(实际上就是进程文件描述符表里的一个数组下标)。要读取数据?read(fd,buff,size)。

这种设计在C语言的纯粹世界里美得像诗。但这种优雅建立在一个隐性假设上:所有的资源,在语义上都可以被抽象成字节流。

但NT设计之初,目标就不是只做一款“更好的Unix”。微软当时要面对的是极其混乱的商业计算环境:要支持多处理器(SMP)、要支持复杂的进程间同步、要支持精细到用户级的权限控制,还要在同一个内核上模拟POSIX、OS/2和Win32多种子系统。

如果你去仔细看NT内核的对象管理器(Object Manager)设计,你会发现一个很残酷的事实:

在操作系统内核里,信号量(Semaphore)、互斥锁(Mutex)、命名管道(Named Pipe)、物理内存映射(Section Object)、甚至是进程(Process)和线程(Thread)本身,它们根本无法被平滑地抽象成“字节流”。

一个线程对象,它有自己的执行上下文、挂起计数、优先级、亲和性掩码(Affinity Mask)。你不可能对一个线程去read()或者write()。

如果你强行把所有东西都套进文件描述符的壳子里,你很快就会碰到那个Unix社区折腾了几十年的老坑:ioctl()爆炸。所有无法用字节流表达的控制逻辑,最后都会变成一堆堆难以维护的二进制控制码。

如果不把所有资源都看作文件,那内核资源在用户态应该怎么表达?

最直白的做法,是直接给用户态返回一个内核对象的内存指针。

在C语言占据统治地位的年代,这种诱惑太大了。如果CreateThread直接返回一个ETHREAD结构体的指针,用户态程序要查询线程状态,直接thread->State读一下不就行了吗?连系统调用的开销都省了。

但Cutler他们在DEC时代就已经踩过这个血窟痛坑。

一旦你把内核结构的内存地址暴露给用户态,不管你加了多少层内存保护,用户程序就会不可避免地对这个地址产生依赖。哪怕你禁止写入,用户态代码也会开始依赖这个指针的偏置(Offset),依赖结构体里某个字段的大小。

后果就是:操作系统内核将永远无法重构。内核只要改动一个字段的位置,全天下所有的应用软件都会崩溃。

更致命的是安全。用户态进程是一个完全不可信的黑暗森林。如果传入一个指针,内核每次使用它,都必须做复杂的寻址检查、页面校验、抢占防御。如果用户态故意传进来一个精心构造的伪造指针,内核一不小心解引用,整个系统就直接Blue Screen。

所以,内核必须建立一道绝对隔离的墙。

这就是HANDLE真正诞生的时刻。

在Windows NT的设计里,HANDLE在逻辑上是一个间接表(Handle Table)的索引,但在语义上,它是一个携带了访问权限(Access Mask)的能力令牌(Capability Token)。

很多人以为HANDLE只是个指针掩码或者简单的数组下标,但其实它背后的机制非常硬核。

当你的进程调用OpenProcess时,内核做了三件事:

发现这个设计精妙的地方了吗?

用户态拿到的HANDLE,本质上是一串没有任何物理意义的符号。你把它加一、减一、或者强转成指针,对内核来说毫无意义。

更重要的是,句柄是绑定在进程上下文里的。进程A里的HANDLE 0x0000000C,和进程B里的HANDLE 0x0000000C,在内核句柄表里指向的可能是完全不同的内核对象,拥有完全不同的权限。

当你拿着这个HANDLE调用TerminateProcess时,内核做的事情不是“去执行终止动作”,而是拿着你的句柄去查表:

  • 这个句柄存在吗?不存在,返回错误。

  • 这个句柄指向的是进程对象吗?类型不对,返回错误。

  • 这个句柄在创建时,是否赋予了PROCESS_TERMINATE权限?没有,拒绝访问。

三关过完,内核才会真正解引用那个内部指针。

这种设计在当年付出了不小的代价——每一次通过HANDLE操作内核资源,都必须经过一次查表和权限硬校验,带来了一点点性能损耗。但是在工程上,它换来了一个极度可怕的优势:系统的强壮性与可演进性。

微软可以在Win95到Win11的三十年间,把内核里的EPROCESS结构体改得妈都不认识,添加无数个调试字段,修改无数次内存布局,而上层的Win32应用程序完全不需要重新编译。因为应用程序手里只有HANDLE,它永远触碰不到内核结构的真相。

这种“用间接性(Indirection)换取解耦与安全”的思路,后来的很多高并发和虚拟化系统都在沿用。

但是,如果只把HANDLE理解成“带权限的间接指针”,其实只理解了一半。

HANDLE能够支撑起整个Windows生态,最重要的另一个拼图,是NT内核强行抽离出的统一同步模型:WaitForSingleObject/WaitForMultipleObjects。

在Unix世界里,很多年来,同步机制都是碎片化的。你等一个文件可读用select/poll;你等一个子进程退出用waitpid;你等一个信号量用sem_wait。它们是完全不同的范式,很难优雅地组合在一起。

而在Windows里,所有内核对象在头头部都有一个共同的底层结构:DISPATCHER_HEADER。

不论是进程、线程、事件(Event)、定时器(Timer)、还是互斥量(Mutex),只要它们是内核对象,内部都有这个Header。这意味着,它们都可以处于两种状态之一:Signaled(有信号)或Nonsignaled(无信号)。

这就导致了一个极其优雅的工程结果:

应用层不需要关心这个HANDLE到底是一个耗时下载的网络套接字、一个正在运行的后台线程、还是一个等待触发的定时器。只要它是一个HANDLE,你就可以直接把它扔进WaitForMultipleObjects。

“当这三个线程结束、或者这个定时器超时、或者这个互斥量被释放,只要其中任意一个发生,就唤醒我。”

这种把所有异步和同步原语统一步骤的设计,在1990年代初的操作系统领域,是极其震撼的。它把复杂的多线程并发控制,收拢到了极少数几个统一的API上。

那这个设计是完美的吗?当然不是。

天下没有免费的午餐,HANDLE的代价同样深刻地影响了Windows的生态。

首先是资源泄漏的诊断成本极其高昂。在Unix上,fd泄露通常很容易定位,因为就那么几个文件。但在Windows上,因为一切皆可HANDLE,当一个大型程序运行几天出现“句柄泄漏”时,你面对的是几万个不知名的内核对象。你根本不知道这个leaked handle到底是个没关的事件,还是某个第三方SDK偷偷创建却忘了释放的线程句柄。

其次,句柄表变成了进程间通信的天然壁垒。因为HANDLE是强绑在进程私有句柄表里的,你想把一个句柄传给另一个进程使用,你不能直接发个整数过去。你必须调用极其繁琐的DuplicateHandle API,让内核在目标进程的句柄表里也拷贝一份槽位。这种设计极大地增加了进程间协同(IPC)的编写复杂度。

更有意思的是,近十年来,随着高性能网络和I/O时代的到来,传统基于HANDLE的同步机制也开始显现疲态。

WaitForMultipleObjects有一个写死在内核里的致命限制:最多只能同时等待64个句柄(MAXIMUM_WAIT_OBJECTS)。

当现代服务器需要处理数万个并发连接时,这种基于对象句柄的等待模型彻底崩塌了。微软不得不后来引入了IOCP(I/O完成端口),乃至近年来在Windows上推行类似io_uring的IORING机制,以此来绕过句柄检索的巨大开销。

现在回看历史,有时候挺有意思的。

Linux在经历了几十年的发展后,也遇到了同样的困境。比如:如何安全地管理进程?早期Linux依靠PID杀进程,但PID会重用。如果在你发信号的瞬间,目标进程刚好退出了,新进程用了同一个PID,你就会误杀一个完全无关的进程。

为了解决这个问题,Linux在内核5.1引入了pidfd_open——通过一个文件描述符来代表一个进程。

当Linux开始把进程、定时器(timerfd)、信号(signalfd)、甚至是事件(eventfd)全都封装成fd,并且在fd上附加各种anon_inode和权限检查时……

你仔细想想,这不就是换了个名字的HANDLE吗?

技术演进到最后,大路通天,大家终究会在同一个物理约束面前相遇。

Unix选择了“一切皆文件”,最后为了解决复杂对象的管理,把fd演变成了能力令牌;Windows选择了“一切皆对象”,通过HANDLE直接把能力令牌做成了底座,代价是承载了数十年的对象系统包袱。

没有哪一种是天生高贵的“优雅”,有的只是工程团队在特定历史时期,为了应对特定复杂度所做出的权衡和妥协。

本内容由作者授权发布,观点仅代表作者本人,不代表虎嗅立场。如对本稿件有异议或投诉,请联系 tougao@huxiu.com。

本文来自虎嗅,原文链接:https://www.huxiu.com/article/4881006.html?f=wyxwapp

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
国产手机失算了,集体涨价几百上千,原以为门庭若市,结果门可罗雀

国产手机失算了,集体涨价几百上千,原以为门庭若市,结果门可罗雀

王新喜
2026-09-04 11:21:22
中国女篮拒绝输球!全力击败捷克队,王思雨复出,央视直播

中国女篮拒绝输球!全力击败捷克队,王思雨复出,央视直播

体坛瞎白话
2026-09-05 08:38:03
儿童患癌越来越多!再三呼吁:这些东西少给孩子吃!危害大

儿童患癌越来越多!再三呼吁:这些东西少给孩子吃!危害大

橘子约定
2026-08-30 14:06:45
开纯电车跑了一趟云南,回来后我默默把车挂上了二手平台

开纯电车跑了一趟云南,回来后我默默把车挂上了二手平台

民间马后炮
2026-09-03 19:49:21
985硕士李雷阳遇难,入职仅5天刚穿上白制服,聊天记录看哭无数人

985硕士李雷阳遇难,入职仅5天刚穿上白制服,聊天记录看哭无数人

小嵩
2026-09-05 14:38:43
绝平被吹!1-2主场惨遭逆转 13.6亿卫冕冠军惨遭爆冷开局3轮不胜

绝平被吹!1-2主场惨遭逆转 13.6亿卫冕冠军惨遭爆冷开局3轮不胜

狍子歪解体坛
2026-09-05 07:20:00
我空降到老婆公司当总裁,开会时坐在她旁边,她男助理竟一脚踹开我的椅子:这是我的位置,你滚开,老婆当场傻眼了

我空降到老婆公司当总裁,开会时坐在她旁边,她男助理竟一脚踹开我的椅子:这是我的位置,你滚开,老婆当场傻眼了

晓艾故事汇
2026-09-04 08:32:39
杨小菁,当选许昌市委书记(附简历)

杨小菁,当选许昌市委书记(附简历)

大风新闻
2026-09-05 16:42:02
网友反映甘肃兰州榆中县存在“染色莴笋”,当地农业农村局工作人员表示:问题莴笋已查封(销毁)

网友反映甘肃兰州榆中县存在“染色莴笋”,当地农业农村局工作人员表示:问题莴笋已查封(销毁)

大风新闻
2026-09-05 14:47:15
女性负债,真的开始“集中爆雷”了。

女性负债,真的开始“集中爆雷”了。

老陆不老
2026-09-04 21:51:34
君子报仇十年不晚!72名以议员直接绕开中国,支持台湾加入国际组织,可他们没想到中国转头支持巴勒斯坦建国

君子报仇十年不晚!72名以议员直接绕开中国,支持台湾加入国际组织,可他们没想到中国转头支持巴勒斯坦建国

扶苏聊历史
2026-09-05 17:13:58
破船永久不走了!国防部这次不再忍,没等菲方闯岛直接给了下马威

破船永久不走了!国防部这次不再忍,没等菲方闯岛直接给了下马威

吕醿极限手工
2026-09-04 17:54:15
大模型蒸馏时代结束!Fable 5.1改写API,彻底切断蒸馏后路

大模型蒸馏时代结束!Fable 5.1改写API,彻底切断蒸馏后路

新智元
2026-09-05 08:01:01
韩媒放狠话!汉字并非中国独有,它是亚洲瑰宝,韩国也将实施全民汉字教育

韩媒放狠话!汉字并非中国独有,它是亚洲瑰宝,韩国也将实施全民汉字教育

小徐讲八卦
2026-09-04 13:48:19
海拔3200米沙漠连夜搜救,1岁裸体走失男童被找到,事件详情披露

海拔3200米沙漠连夜搜救,1岁裸体走失男童被找到,事件详情披露

扬子晚报
2026-09-05 10:55:31
武大学术圈妲己上位后续:女方被曝更多猛料,她从小就是乖乖女!

武大学术圈妲己上位后续:女方被曝更多猛料,她从小就是乖乖女!

小娱乐悠悠
2026-09-05 14:51:35
罗志祥复出登上热搜,《极限挑战》导演发布长文:六人齐聚才是极限挑战,并询问观众是否期待重拍

罗志祥复出登上热搜,《极限挑战》导演发布长文:六人齐聚才是极限挑战,并询问观众是否期待重拍

新浪财经
2026-09-05 12:05:31
一辆中国SUV让《纽约时报》实测10天,并推出整版报道;美消费者破防:我们可能永远买不到

一辆中国SUV让《纽约时报》实测10天,并推出整版报道;美消费者破防:我们可能永远买不到

第一财经资讯
2026-09-05 12:44:09
“韩国考虑向霍尔木兹海峡派遣海军”,韩媒披露原因

“韩国考虑向霍尔木兹海峡派遣海军”,韩媒披露原因

参考消息
2026-09-05 17:29:04
武大举报风波升级!终于查实:付磊教授的原配妻子为汪海英,曾任该校的行政干部

武大举报风波升级!终于查实:付磊教授的原配妻子为汪海英,曾任该校的行政干部

火山詩话
2026-09-05 17:49:34
2026-09-05 19:52:49
虎嗅APP incentive-icons
虎嗅APP
个性化商业资讯与观点交流平台
27627文章数 688049关注度
往期回顾 全部

科技要闻

华为何庭波,再次更新韬定律论文

头条要闻

知名摇滚歌手何勇去世 崔健曾评价"这小子真了不起"

头条要闻

知名摇滚歌手何勇去世 崔健曾评价"这小子真了不起"

体育要闻

小卡来去10首轮,快船7年彩礼一场空

娱乐要闻

她曾被名导抛弃,凭《生逢其时》翻红

财经要闻

被曝试药后死亡,药企董事竟怒怼记者

汽车要闻

全新第四代博越Li‑HEV系列 怎么开都省

态度原创

教育
家居
时尚
亲子
健康

教育要闻

最高投档660分!2026江苏这6所211有多难考?

家居要闻

2026建博会(广州) 公装联探展交流活动

杨紫:自渡成舟

亲子要闻

“你该长大了”,宝妈撒娇痛哭,不愿走1.5公里送娃上学,力竭了

脑梗取栓成功≠活下来,还有这三关

无障碍浏览 进入关怀版