惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tailwind CSS Blog
J
Java Code Geeks
Engineering at Meta
Engineering at Meta
博客园_首页
G
Google Developers Blog
有赞技术团队
有赞技术团队
Vercel News
Vercel News
Last Week in AI
Last Week in AI
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
IT之家
IT之家
The GitHub Blog
The GitHub Blog
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - Franky
A
About on SuperTechFans
The Register - Security
The Register - Security
腾讯CDC
月光博客
月光博客
GbyAI
GbyAI
博客园 - 叶小钗
Blog — PlanetScale
Blog — PlanetScale
D
Docker
D
DataBreaches.Net
博客园 - 聂微东
C
Check Point Blog
T
The Blog of Author Tim Ferriss
人人都是产品经理
人人都是产品经理
F
Full Disclosure
Martin Fowler
Martin Fowler
Apple Machine Learning Research
Apple Machine Learning Research
雷峰网
雷峰网
美团技术团队
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 司徒正美
小众软件
小众软件
量子位
L
LangChain Blog
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog
大猫的无限游戏
大猫的无限游戏
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
I
InfoQ
F
Fortinet All Blogs

Linux

[震惊] 用 Firefox 播放一个抖音视频,我的 Linux 系统立马死机 - V2EX 强烈推荐一款性价比极高的 Linux 本搞 vibe coding - V2EX Linux 下有没有可能实现 Listary 的快速跳转 - V2EX AI 能用来全自动化解决 Linux 系统问题吗? - V2EX V2EX › 登录 大佬们, Linux kernel 漏洞频发需要升级的问题,你们是怎么处理的? - V2EX 为啥 ubuntu 搞个 wayland 这种不兼容的玩意出来 - V2EX Linux 上的游戏网络加速 - V2EX 太好了感动哭了 chrome149 修复了 wayland+nvidia 的硬件加速问题 - V2EX debian+gnome 开机后可以不显示用户列表 只需要输入密码 像 mac 那样么?有什么插件实现么 - V2EX 升级后,发现 USB 相关的设备无法启用,可以查下有没有 usbguard 服务 - V2EX 介绍一下 flatpark - V2EX fctix5 的 Pinyin 输入法怎么没有自动调整词频 - V2EX Linux 服务器有何安全监控软件? - V2EX 腾讯会议 Linux 版使用 nvidia 独显无法驱动视频功能 - V2EX niri 环境用触控板怎么能更好的选择文字 - V2EX 『ArchLinux』简明安装指南(Laptop+Nvidia+Cachyos Kernel +xfs+KDE) 有没有使用 Linux 桌面办公的朋友,我写了一个脚本可以实现快速查单词/翻译句子 国产 Touchpad 在 arch 下偶发无法用手势 《铜豌豆 Linux 》12.14.1 版本发布 wgx 一个以性能优先 把 wireguard 网络转成 socks5 代理的工具 niri 怎么连自动切换显示器都这么难啊 分享 tmux 快捷方式 zen 浏览器在 archlinux 中无法代理 albert 快捷键总是失效 - V2EX crTerm 148.26.0513-build for Linux Linux 平台上 支持垂直标签页的终端 crTerm 苹果最新妙控触摸板和 Linux 适配的好吗? - V2EX ubuntu 24.04 今天点击更新后,蓝牙鼠标不能用了。 升级到 fedora 44 后在 konsole 里打字时 cpu 占用很高的问题有 v 友也遇到了吗? Ubuntu26.04 桌面端配置静态 IP 失败 Gnome 桌面下截图上传到 imgur 的 extension - V2EX Manjaro 真不错 - V2EX 写了个 lottie 动画在 Linux 桌面上顶层播放的小东西 - V2EX LXC veth 桥接网络模式下如何避免发送的数据包被拆成小包? - V2EX 使用 auto-cpufreq 平衡 Linux 性能功耗 我的硬盘 Memblaze Pblaze 5 Linux 下不识别,给 Linux 内核提交了补丁, AI 说有望被合并 - V2EX Linux nfs 客户端如何快速删除大量小文件 写了个 Nautilus Extension: Copy File Path - V2EX Linux /Ubuntu 上如何实现连接两个不同的 wifi 解决实际需求。 - V2EX 115 网盘如何多端稳定挂载? - V2EX Linux 桌面环境 orWM 推荐 - V2EX 如何解决 eBPF sockmap 重定向转发中背压缺失带来的 OOM ? - V2EX 还是要用 ubuntu - V2EX nfs mv 的操作是原子的么? A 节点 move, B 节点要么完全可见,要么完全不可见? - V2EX 求助 Linux 桌面环境软件 - V2EX 请教一个 unraid 的 docker 网络问题 - V2EX Linux 格式化 fat32/exfat 分区避坑 - V2EX Linux 服务器上有多个 ip,程序本身不能指定接口,有第三方程序可以强制让程序使用指定接口吗? - V2EX Ubuntu 26.04 LTS 关键变化解读 - V2EX win11 对比 ubuntu,是真的拉胯 - V2EX 终于把 KeymouseGo 跑在麒麟 9000C + UOS 上了,分享一下 ARM64 适配心得 - V2EX sudo-rs 改变传统 sudo 行为,密码输入不再完全隐藏,即将上线 Ubuntu 26.04 LTS - V2EX Xdmcp 服务问题使用与优化求解 - V2EX 在 2026 年选择 Fedora 前,你应该看看 universal-blue - V2EX Linux 运行 EasyConnect 有成功的大佬么? - V2EX 我有一批工控机,批量内网穿透加群控什么方案合适 - V2EX 求推荐 Linux 桌面 - V2EX Linux 微信怎样避开实名信息录入? - V2EX 再来谈谈我的 ArchLinux 使用体验 - V2EX thinkbook 14+ 2024 Intel 版安装 arch plasma 左右声道声音大小不一样 - V2EX 有没有便宜好用的服务器推荐 - V2EX 能不能改改 networkmanager 中的错别字? - V2EX 《铜豌豆 Linux 》12.13.1 版本发布 2026-01-16 - V2EX Wayland 显示服务下的远控方案 - V2EX 深度科技原 cto 关于西装门的每日锐评 - V2EX 求大佬们分享下跨境组网方案 2026 年了,有没有丝滑一些的 Linux 远程桌面解决方案 Linux 下看电影, dts 音轨声音小,音质破。 华为擎云 W515X 支持运行 openSUSE 等发行版吗 折腾两天还是换回 Manjaro Arch Linux 下微信备份聊天记录的方案? 国内 Linux 服务,安装各种软件有什么好的办法快速安装? 垃圾佬组 Linux 求推荐亮机卡 有个 javac 进程长期占用,是否被挂马了? 荣耀笔记本与 Linux - 性能管理 Linux 漫谈(二) 完整启用 Fedora/ Linux 下 GNOME 的硬件加速 Linux 漫谈(一) 铜豌豆 Linux 开源项目 2025 年 12 月捐赠募集
Linux 漫谈(三)
kuanat · 2025-12-28 · via Linux
之前的章节: https://v2ex.com/t/1180785 https://v2ex.com/t/1181027 0x30 IPC 是妥协的艺术 之前讲过了,几乎无论什么时候性能都是个永恒的追求,内核也不例外。所以在九十年代初期,开发者有机会从零设计一款操作系统内核的时候,很多方面都要为了性能作出让步。 其中受影响最大的便是 IPC 的设计,它不仅仅是受性能影响这么简单,更重要的是 IPC 的设计代表了设计者对于软件交互逻辑的理解,也决定了未来这个操作系统上,所有的应用程序要如何编写,可谓是决定性的要素。 用今天的眼光重新审视 linux/NT/XNU 当年的设计,我个人所能总结的经验教训就是:不可能有一种完美的、能够适应所有时代需求的方案,所以取舍就变得很重要,不能既要又要。 在回答如何设计 IPC 这个问题之前,更重要的问题是为什么要有 IPC ,这里特指内核控制中,不同于传统 Unix 提供的 socket/pipe 实现。而要回答这个问题,就要考虑九十年代初这个时间节点,图形化的应用程序是怎么写的。 今天看起来非常普遍的图形应用开发范式:比如 UI 和逻辑线程分离,再比如异步 RPC 调用,在图形操作系统刚出现的时候还不存在。甚至几乎没有多少真正意义上的“多线程”应用程序,因为不仅当时的 CPU 没有多核心设计,而且同时期的 Unix 还只有 fork ,而更轻量化的线程( thread )直到 1995 年才定稿。 对于大多数应用开发者来说,只需要考虑系统或者底层提供了什么样的 API 可以使用即可。而对于基础库或者操作系统的开发者来说,这个思考过程是反过来的: 先想象未来的图形 App 是什么样子,要如何编写; 之后发现现在的 C 语言和硬件支持不了这种编程范式; 确定需要在内核里增加一套支撑机制; 将内核机制封装为用户态可用的图形库供开发者使用。 于是尽管目前的章节要讨论的是 IPC 设计,实际的切入点却是图形界面应用程序。(理论上在操作系统进入多任务时代的时候,非图形界面应用程序之间也有 IPC 需求,但图形界面应用程序更具代表性,需求也更加一般化) 0x31 现代图形界面的基础 在正式讨论开始之前,先补充一些背景知识。 现代意义上的图形界面最早是 1973 年由 Xerox Alto 计算机实现的,Alan Kay 等人设计了 GUI 软件界面以及相应的操作工具:鼠标。此时工程师们意识到,传统的线性应用程序遇到一个难题,即程序并不知道用户下一秒是要操作鼠标还是键盘,或者是其他操作。 于是 Dan Ingalls (也就是 Smalltalk 的设计者)提出了一种新的应用程序结构,主程序启动不再退出而是进入一个循环,循环中程序会轮询或等待中断调用。这个模式也称为 RunLoop 一直沿用到今天。 得益于那个时代面向对象理论的快速发展,开发者很快意识到,鼠标键盘输入和 IPC 消息等等都可以抽象成事件,操作系统只需要将事件发送给不同的应用(即多消息队列)就可以支持多任务,包括 MVC 这样的概念也就是那个时期就已经成熟了。后来 Smalltalk-80 将其抽象化成了今天熟知的 EventLoop 模式。 不过真正意义的“多任务”操作系统是很久之后的事情了。还记得之前提到的 2003 年 Linux 2.6 版本实现的所谓“抢占式”机制吗?所谓抢占式( Preemptive )就是与协作式( Cooperative )相对应的,协作式简单说就是应用程序自己才能决定退出,而抢占式指的是内核调度器可以主动打断并切换当前运行的进程。 这里我们能看出,内核的抢占式支持是基础,而操作系统的多消息队列同样重要。1995 年发布的 Windows 95 版本首先支持了图形界面抢占(仅限 32 位应用),每个 UI 线程都有一个独立的消息队列。而 Classic Mac OS 就一直只有协作式图形界面,直到 2001 年的 Mac OS X 10.0 使用了 XNU 内核之后才实现抢占式图形界面支持。 严格来说“抢占式内核”指的是当执行内核 syscall 的时候能否被打断,比如说执行某个慢 io 操作时,如果希望同时播放音频,在非抢占式内核上就要等之前的 syscall 调用完成,在抢占式内核上当之前的 syscall 时间片到期后,播放音频的指令就可以被执行。也就是说,即便是非抢占式内核,也可以实现抢占式的图形界面逻辑,只是一般来说图形界面要求低延迟,在抢占式内核上这样做才有意义。 对于 Linux 来说,由于它从第一天起就没有专属的图形界面,很长一段时间中 X 就是事实上的图形界面标准。所以是否能支持抢占式图形界面,完全取决于 X 自己的实现。由于 X Server 只是一个运行在用户空间的应用程序,而内部的消息队列又是基于 socket 实现的,所以天然就获得了图形界面的抢占式特性。 技术层面它是两个原因的共同结果,一方面是底层 IPC 走的是 socket ,在内核侧是有缓冲的,另一方面 X 设计为 C/S 架构,单个 Client 阻塞绝大多数时间不会造成 Server 的阻塞。这里就不展开讲了。 之所以 Windows 95 没有实现 16 位应用的抢占式图形系统支持,是因为早期基于协作式多任务的应用程序代码,在抢占式环境中不是线程安全的。Classic Mac OS 也有类似的问题,所以后来 Mac OS X 10.0 之后就放弃支持完全重做了。 0x32 图形应用到底应该怎么写? 在协作式时代,没有操作系统层面的调度器,那应用程序可以随便写,反正在应用程序主动交出控制权之前,内存和图形库也是全局独占的,不需要考虑线程安全的事情。 到了抢占式时代,操作系统的设计者要考虑的问题就变成了:如何解决线程安全的问题? 回到之前提到的设计者思考路径: 很明显 Run/Event Loop 的模式是不会变的; 最好还能保持协作式时代的写法,而且让应用侧去控制显存锁不合理也不现实; 内核侧应该主动去控制显存锁,这样某个时刻就只有一个应用在访问显存,但这样就会导致大量用户态和内核态之间的上下文切换; 内核为了隔离和安全,并不想将内部 IPC 机制完全暴露,所以要通过某种协议提供用户态的高级封装,供应用程序来调用。这个 IPC 机制可以不局限于图形界面绘制,也可以一般化为应用程序之间的交互方式,但是性能要好。 绕了这么一大圈,终于回到了 IPC 的话题上。不过这个逻辑是我本人的推理,并没有哪个知名人士以访谈或者回忆录等形式记述这段历史发展历程。 关于图形系统的部分再稍微补充一点,其他留到之后的章节再讨论。 现代图形系统的核心逻辑是合成器模式,每个应用程序在自己私有内存空间中进行绘图,由操作系统提供的合成器按需合成后交给显卡现实。在 2000 年之前是不具备这个条件的,因为当时的电脑内存太小了,整个系统只能保留一个公共的显存,无法让每个应用都有自己的绘制空间。所以当时的图形系统核心是失效重绘的模式,即内核维护显示输出的失效状态,然后调用对应的应用程序对失效部分进行重绘。 0x33 IPC 的世界观 以今天的眼光来看,IPC 机制本质上就是一套协议,这套协议在内核语境下,应该具备以下特性: 载荷无关( Payload Agnostic ),即 IPC 的信息传递对于内核来说是透明的,解析是由 IPC 通信的参与者完成。 异步交互( Async Interaction ),描述的是 IPC 调用的时空边界。可以通过底层异步来模拟同步调用,但需要明确它的执行代价(和 RPC 做区分)。 能力导向( Capability Oriented ),主要说的是 IPC 调用的安全边界,声明式的权限控制是目前实现容器化安全的底层机制。 这里描述的是通用的设计通用通信协议的一般原则。这是全世界的开发者们用了几十年时间,在各个领域进行了不同的尝试,如今总结出来了经验教训。注意这里描述的是一般设计原则,并非实现技术。从技术层面上说,同一种目标可以有很多不同的实现手段。 实践中可以在实现层面,为了达到特定目的而做一些不完全符合设计原则的调整,但一定要清楚它的代价。还是之前那句话,取舍是一种智慧,不能既要又要。这样说可能不是很好理解,我这里就专门列举一下,那些曾经的设计失误,以及由此产生的后果。 “不要误会,我不是要针对谁,我是说在座的各位……” 0x34 混乱的 D-Bus D-Bus 诞生于 2002 年,这里 D 的意思是 Desktop 桌面。这个协议基本上是 GNOME 桌面的人开发的,是的,还是 Red Hat 的人。这个协议设计之初的目的是替代 KDE 的 DCOP 协议,以方便移除 Qt/X11 等依赖。(实际上目前 Freedesktop.org (Fd.o) 旗下的 systemd/Wayland/NetworkManager/PulseAudio/PipeWire 也都是红帽的人在主力维护) 如果你没有基于 D-Bus 写过代码,可能不太好理解 D-Bus 的工作原理。简单说它是一个消息总线,任何程序可以注册任意对象,也可以在任意时间用任意方式去访问总线上的任意对象。你看我用了这么多“任意”,应该能猜到这是一个鼓励“动态化”的协议。(技术上是通过发送消息的方式实现的,而不是调用函数,这里为了方便描述简化了) 所以它就选择了 XML 作为交换格式( 2002 年的时候还没有 JSON 什么事)。按照协议设想,应用程序或者说服务方要主动声明自己具有哪些能力,方便其他应用使用,这个机制叫做 Introspection 自省。如果调用特定的自省接口,就可以通过 XML 获得所有接口以及对应的能力。(准确说 XML 只用于接口自省,实际上传输的数据 WireFormat 是二进制的) 听起来很美好是吗?实际上无论是 D-Bus/DCOP 都是 NeXTSTEP/Smalltalk 思想的延伸。D-Bus 设想中的自己,应该是和 macOS 上“服务”一样的效果,应用程序可以枚举出当前系统所有能够提供功能的服务端,然后调用对应的功能。然而现实是 Linux 生态极其碎片化,同时工具链支持也非常弱,就导致了完全不一样的效果。 桌面开发大部分时间都是用 C/C++ 的,实现一个 XML 解析是非常痛苦的事情。2002 前后可没有 GitHub 这样的服务,C 生态中造轮子是常态。GNOME 为了解决这个问题,创造了 GObject/GVariant 类型系统,并提供了配套的代码生成工具。桌面应用开发者的工作可以不再解析 XML 而是用工具来生成。 但 XML 编写本来就麻烦,修改一次接口就要重新生成代码再编译,开发者们就开始找捷径,于是 a{sv} (Array of String-Variant) 登场了。这玩意就是个字典,键是字符串,值是任意类型。传递一个 a{sv} 之后,整个世界清净了,再也不用每次改接口都重走一遍构建了。 这样一来 XML 存在的意义也彻底没了,自此之后,什么 D-Bus 规范、Fd.o 白皮书都滚蛋吧,没人在意,也没人去写了,一切以约定为准。 我就想问问,“一切以约定为准”是不是听起来很耳熟,数组传数据结构是不是很爽,大家有没有在工作中干过类似的事情?只能说,大家都是草台班子,谁也别笑话谁。 当然 D-Bus 协议还有其他问题,主要是安全性方面的。最早的 D-Bus daemon 实现也全是坑,这个等以后专门再讲。相对来说,安全性是受限于时代性的,而且解决起来也不是那么困难。还有一点要注意,D-Bus 虽然是目前 Linux 桌面的实际 IPC 标准,但它却不在 Linux 内核中。 高情商的说法是,今天 Linux 桌面还能用,而且看起来跑得不错,D-Bus 的再实现起了关键性作用。换个说法,今天的碎片化程度,D-Bus 要先把锅背好。 我这里一定要提一个草台班子的事情。为什么我一直强调说,类似 LKML 这样的讨论比代码更有学习价值,就是因为对话和文字记录中可以看出来开发者是怎么想的,他为什么要做某种设计,这样的经验无比珍贵。因为经验这个事属于知道就是知道,而不知道就是不知道,不知道的情况下一定会重复踩别人踩过的坑。 目前的 MCP 协议,精神上和 D-Bus 没有任何不同,协议规范层面,就是用 JSON 代替了 XML 。而且得益于现代工具链,开发者偷懒的机会变少了。但是机制上,如果开发者都在 payload 中塞一个类似 a{sv} 的字典,一样会完蛋。 所以说不是用上现代技术就能避免设计上的误区了,编程这件事在哲学层面大致是相通的,人类世界的复杂程度并没有因为新技术而变得更高,反倒是设计理念这种理论会一直保持下去。 这一章节内容比较长所以分开了,后面还会接着锤其他的设计。