产品中心
发布日期:2026-08-09 02:15 点击次数:67

玉林预应力缓粘结钢绞线 微软为什么无须指针,而要多绕层?

钢绞线

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

约略是在七八年前,我其时在学习 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 告成把智商令作念成了底座,代价是承载了数十年的对象系统职守。

莫得哪种是天生贵的"雅",有的仅仅工程团队在特定历史时期,为了应酬特定复杂度所作念出的量度和和谐。手机号码:15222026333相关词条:不锈钢保温     塑料管材设备     预应力钢绞线    玻璃棉板厂家    pvc管道管件胶

1.本网站以及本平台支持关于《新广告法》实施的“极限词“用语属“违词”的规定玉林预应力缓粘结钢绞线,并在网站的各个栏目、产品主图、详情页等描述中规避“违禁词”。
2.本店欢迎所有用户指出有“违禁词”“广告法”出现的地方,并积极配合修改。
3.凡用户访问本网页,均表示默认详情页的描述,不支持任何以极限化“违禁词”“广告法”为借口理由投诉违反《新广告法》,以此来变相勒索商家索要赔偿的违法恶意行为。

推荐资讯
友情链接: