一句话:"1"不是某种神秘的东西,它通常就是某个地方存着一小堆电子(或者某根导线上有较高的电压)。电脑只是约定:电压高于某个值算 1,低于某个值算 0。
前面讲网络时,我们一直在说"字节"“位”“包”。这一篇往下挖到底:一个位,在物理上到底是什么。
一、生活里的例子:一排水杯
桌上摆着 8 个水杯:
- 杯里有水 → 记作1
- 杯里没水 → 记作0
8 个杯子就能表示一个字节,比如01000001(字母 A)。
但现实中会有几个麻烦:
| 水杯的问题 | 电脑里对应的问题 |
|---|---|
| 杯子有细缝,水会慢慢漏掉 | 电荷会泄漏,所以 DRAM 需要不停刷新 |
| 杯里只剩半杯水,算有还是没有? | 需要一个阈值来判断 |
| 想知道有没有水,只能倒出来看 | DRAM 的读取是破坏性的,读完要写回 |
| 杯子用久了会裂 | 闪存(SSD)的擦写寿命 |
“充电状态"就是"杯子里有水”。下面看看不同的"杯子"分别是什么。
二、先搞清楚"充电"是什么意思
电荷与电压
- 电荷:物质里带电粒子的多少。电子带负电,一个电子的电量约为 1.6 × 10⁻¹⁹ 库仑。
- 电压:两点之间的"电势差",可以理解为"水位差"。
“充电"并不是"装进了电”,而是把电子从一边搬到另一边,让两边形成电压差。
电容器:最简单的"杯子"
┌─────┐ ← 一块金属板:电子被抽走,带正电 │ 绝缘 │ ← 中间是绝缘层,电子过不去 └─────┘ ← 另一块金属板:电子堆积,带负电存了多少电荷,取决于两个因素:
Q = C × V 电荷量 = 电容大小 × 电压电荷存在那里,两板之间就有电压,电路可以检测到这个电压。
"1"其实是一个电压范围
数字电路不要求电压正好是某个值,而是按范围判断:
电压 1.0V ┤██████████ 判定为 1(高电平) 0.7V ┤────────── 高电平阈值 │ 不确定区 ← 落在这里结果不可靠,电路设计会尽量避免 0.3V ┤────────── 低电平阈值 0V ┤██████████ 判定为 0(低电平)中间留出来的空白区叫噪声容限:即使有点干扰、有点漏电,只要没跨过阈值,0 还是 0,1 还是 1。
这就是数字比模拟可靠的根本原因:模拟信号每一点误差都会被记录下来,数字信号只要不越过阈值,误差就会被"抹掉"。
三、DRAM(内存条):最典型的"充电 = 1"
你电脑里的内存条就是 DRAM。每个位由1 个晶体管 + 1 个电容组成(简称 1T1C):
字线(Word Line):选中这一行 │ ┤ 晶体管(开关) 位线 ───────┤ (Bit Line) │ ═╪═ 电容:存电荷 │ 接地| 状态 | 电容 | 含义 |
|---|---|---|
| 充了电 | 有电压 | 1(也可以反过来约定) |
| 没充电 | 接近 0V | 0 |
一个"1"到底有多少电子?
现代 DRAM 单元的电容大约在10 fF(飞法,10⁻¹⁵ 法拉)量级,工作电压约 1V:
Q = C × V ≈ 10 × 10⁻¹⁵ × 1 = 10⁻¹⁴ 库仑 电子数 ≈ 10⁻¹⁴ ÷ (1.6 × 10⁻¹⁹) ≈ 60,000 个你内存里的一个"1",大约就是几万个电子挤在一个极小的电容里。16GB 内存有约 1370 亿个这样的电容。
漏电 → 必须刷新
绝缘层不完美,电子会慢慢漏走。几十毫秒后,“1"就可能变成"0”。
所以内存控制器会定期把每一行读出来再写回去,标准规定通常每64ms内要把所有行刷新一遍。
写入 1: ████████████ 过了一会:████████░░░░ 电子在漏 刷新: ████████████ 读出来,判定为 1,重新充满这就是"DRAM"中 D 的意思:Dynamic(动态),需要不停维护。断电后,刷新停止,几秒到几分钟内数据就消失了。
读取会破坏数据
位线本身的电容比单元电容大得多(可能大 10 倍以上)。打开晶体管后,单元里的电荷分摊到位线上,位线电压只变化几十到一百多毫伏。
1. 先把位线预充到中间电压(比如 0.5V) 2. 打开晶体管,单元电荷和位线混合 3. 位线电压变成 0.55V(单元原来是 1)或 0.45V(原来是 0) 4. 灵敏放大器(Sense Amplifier)把这个微小差别放大成完整的 1 或 0 5. 放大后的结果顺便写回单元,恢复电荷这就像用一个大杯子去量小杯子里的水:倒进去后只能看到水面轻微上升,还得用放大镜判断,然后再把水倒回来。
四、SRAM(CPU 缓存):不靠存电荷,靠"互相撑住"
CPU 的 L1、L2、L3 缓存用的是 SRAM,每个位用6 个晶体管:
┌──→ 反相器 A ──┐ │ ▼ └─── 反相器 B ←─┘ A 输出 1 → B 输出 0 → A 继续输出 1 → ……两个反相器(把 1 变 0、把 0 变 1 的电路)首尾相接,形成互相锁定的稳定状态。
| DRAM | SRAM | |
|---|---|---|
| 怎么存 | 电容里的电荷 | 两个反相器互相维持的电压 |
| 每位晶体管数 | 1 个(+ 1 个电容) | 6 个 |
| 需要刷新吗 | 需要 | 不需要(只要通电) |
| 速度 | 较慢 | 很快 |
| 密度 / 成本 | 密度高、便宜 | 占地大、贵 |
| 用途 | 内存条 | CPU 缓存、寄存器附近 |
SRAM 的"1"不是一堆静止的电子,而是电源持续供电撑住的一个电压状态。就像两个人背靠背站着互相支撑,只要有力气(供电),谁都不会倒。
这也解释了前面讲性能时说的:缓存很快但很小,因为每一位都很"贵"。
五、闪存(SSD、U 盘、手机存储):把电子关进笼子
闪存断电后数据还在,靠的是浮栅(Floating Gate)或电荷捕获层:
控制栅 ═════════════ 绝缘层(很薄) ┌───────────┐ │ 浮 栅 │ ← 四面都被绝缘层包住的"笼子" └───────────┘ 绝缘层(很薄) ═════════════ 源极 沟道 漏极| 操作 | 原理 |
|---|---|
| 写入(编程) | 加较高电压,让电子隧穿绝缘层进入浮栅(量子隧穿效应) |
| 保存 | 断电后电子被绝缘层困住,可以保存数年 |
| 读取 | 浮栅里的电子会改变晶体管的导通门槛(阈值电压),测一下导不导通就知道 |
| 擦除 | 加反向高压,把电子拉出来 |
⚠️ 这里"充电"反而表示 0
NAND 闪存中,按惯例:
| 状态 | 浮栅 | 值 |
|---|---|---|
| 擦除后 | 电子很少 | 1 |
| 编程后 | 电子较多 | 0 |
所以**"充电 = 1"只是一种约定,不是物理定律**。一块全新、擦除干净的闪存,读出来全是0xFF(全是 1)。
一个位用多少电子?越来越少
| 类型 | 每个单元存几位 | 需要区分的电荷等级 |
|---|---|---|
| SLC | 1 位 | 2 级 |
| MLC | 2 位 | 4 级 |
| TLC | 3 位 | 8 级 |
| QLC | 4 位 | 16 级 |
工艺越先进,单元越小,每个等级之间相差的电子数就越少,有时只有几十个电子的量级。QLC 要在同一个笼子里分辨 16 种"满的程度",就像在一个杯子里分辨 16 种水位。
| 后果 | 原因 |
|---|---|
| 寿命短(擦写次数少) | 每次隧穿都会轻微损伤绝缘层,笼子越来越"漏" |
| 需要强力纠错(ECC、LDPC) | 少几个电子就可能被误判 |
| 长期断电可能丢数据 | 电子会极其缓慢地漏出 |
| 速度较慢 | 写入要多次"充一点、测一下",逐步逼近目标电荷量 |
六、其他地方的"1"
| 位置 | "1"是什么 |
|---|---|
| CPU 寄存器 | 触发器(类似 SRAM 的锁存结构)输出的高电压 |
| CPU 内部导线 | 导线被充到高电压(导线本身也有微小电容) |
| 机械硬盘 | 磁性颗粒的磁化方向,没有电荷 |
| 光盘 | 反射面上的凹坑与平面之间的变化 |
| 网线 | 电压在一段时间内的变化模式(还经过编码) |
| 光纤 | 光脉冲的有无或强弱 |
| Wi-Fi / 4G | 电磁波的相位和幅度组合,一个符号可以携带多位 |
上一组网络文章里讲的"包"“带宽”,到了最底层就是这一行:网线上的电压跳变、光纤里的光闪烁。网卡把这些物理信号翻译成 0 和 1,再交给内核。
七、为什么电脑会发热?因为一直在"充放电"
CPU 里有几十亿个晶体管,导线和晶体管栅极都相当于微小电容。每次一个位从 0 变 1,就要给这些电容充电;从 1 变 0,就要放电,能量变成热量。
CPU 的动态功耗大致是:
P ≈ α × C × V² × f α:每个周期有多少比例的电路在翻转 C:被充放电的电容总量 V:电压 f:频率| 结论 | 说明 |
|---|---|
| 电压影响最大(平方关系) | 电压降低 10%,功耗约降低 19%,所以降压是笔记本、手机省电的主要手段 |
| 频率越高越热 | 每秒充放电次数更多 |
| 数据翻转越多越耗电 | 一直不变的位几乎不耗动态功耗 |
和游戏开发的联系:手机游戏"发烫降频",本质就是每秒充放电的次数和电量太多,热量散不出去。降低帧率、减少无用计算,等于减少充放电次数。
八、“1"会不会自己变成"0”?会
| 原因 | 说明 |
|---|---|
| 漏电 | DRAM 靠刷新、闪存靠纠错和定期重写来应对 |
| 宇宙射线 / 高能粒子 | 粒子穿过芯片产生电荷,可能翻转一个位(单粒子翻转),高海拔、航天设备更明显 |
| Rowhammer | 反复高频访问 DRAM 某一行,相邻行的电容受干扰漏电更快,可能翻位,曾被用于安全攻击 |
| 电压不稳 / 过度超频 | 信号还没稳定到阈值以上就被读取 |
| 闪存磨损 | 绝缘层损坏,电荷关不住 |
应对方法:
| 方法 | 用在哪里 |
|---|---|
| ECC 内存 | 服务器内存,自动纠正单位错误 |
| 校验和 / 哈希 | 网络包、文件下载(CDN 那一篇的"下载后校验哈希") |
| 闪存控制器的 LDPC 纠错 | SSD 内部 |
| 冗余与重试 | 网络可靠传输(ACK 与重传) |
前面网络篇讲的"校验 + 重传",和内存的 ECC 是同一个思想:物理世界的 0 和 1 并不完美,可靠性是靠上层机制补出来的。
九、用代码模拟一下 DRAM 漏电与刷新
用一个简单模型直观感受:电荷按比例泄漏,低于阈值就读错。
usingSystem;classDramCell{publicdoubleVoltage;// 当前电压constdoubleVdd=1.0;// 满电电压constdoubleThreshold=0.5;// 判定阈值constdoubleLeakPerMs=0.01;// 每毫秒泄漏 1%(简化)publicvoidWrite(boolbit)=>Voltage=bit?Vdd:0.0;publicvoidTick(doublems)=>Voltage*=Math.Pow(1-LeakPerMs,ms);publicboolRead(){boolbit=Voltage>Threshold;Write(bit);// 读取是破坏性的,读完写回(相当于刷新)returnbit;}}classProgram{staticvoidMain(){varnoRefresh=newDramCell();varwithRefresh=newDramCell();noRefresh.Write(true);withRefresh.Write(true);for(intt=0;t<=120;t+=10){Console.WriteLine($"{t,4}ms 不刷新:{noRefresh.Voltage:F2}V "+$"定期刷新:{withRefresh.Voltage:F2}V");noRefresh.Tick(10);withRefresh.Tick(10);if(t%40==30)withRefresh.Read();// 每 40ms 刷新一次}Console.WriteLine($"不刷新读到:{(noRefresh.Read()?1:0)}");// 0:数据丢了Console.WriteLine($"定期刷新读到:{(withRefresh.Read()?1:0)}");// 1:数据还在}}运行后能看到:不刷新的那个单元,大约 70ms 后电压跌破 0.5V,“1"变成了"0”;定期刷新的始终保持在阈值以上。(真实 DRAM 的泄漏速度和刷新机制比这复杂得多,这里只是演示原理。)
十、常见的误解
| 误解 | 实际情况 |
|---|---|
| “1 就是有电流流过” | 通常是有电压(电荷积累),不一定有电流;SRAM 和 DRAM 保持状态时几乎没有电流 |
| “充电一定是 1” | 只是约定;NAND 闪存里电子多反而是 0 |
| “1 就是正好 1 伏” | 是一个电压范围,靠阈值判断 |
| “内存断电马上清零” | DRAM 电荷要逐渐泄漏,低温下甚至能保留数秒以上("冷启动攻击"就利用了这一点) |
| “硬盘也是靠充电” | 机械硬盘靠磁化方向,不靠电荷 |
| “数字信号不会出错” | 会,只是有阈值和纠错机制挡住了大部分错误 |
| “存储里的数据是永久的” | 闪存会老化和漏电,长期不通电的 SSD 有丢数据风险,重要数据要备份 |
一句话总结
"1"在物理上通常是:某个地方积累了一些电子,形成了高于阈值的电压。
- DRAM:电容里约几万个电子,会漏电,所以每几十毫秒要刷新一次,读取时还会被破坏、需要写回。
- SRAM:两个反相器互相锁住的电压状态,只要通电就能保持,快但贵。
- 闪存:电子被隧穿关进浮栅,断电也能保存;而且按惯例,电子多的是 0。
不管哪一种,"1"都只是物理状态 + 人为约定 + 阈值判断。计算机之所以可靠,是因为在这些并不完美的物理状态之上,又叠加了阈值、刷新、纠错和校验。