news 2026/10/28 13:03:48

cloudflare-os:为Cloudflare源站打造的精简Linux与内核优化实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
cloudflare-os:为Cloudflare源站打造的精简Linux与内核优化实践

如果你和我一样,把一堆业务源站放在 Cloudflare 后面,那你大概率也遇到过这种怪事:明明服务器 CPU 和内存都闲着,可回源请求总是比预期慢一截,日志里还全是来自世界各地的端口扫描记录。我花了大概三个月时间,把整套环境重构成了一个叫 cloudflare-os 的最小化镜像项目——它不依赖任何重量级发行版,整个系统就为一个目的服务:在 Cloudflare 边缘网络后面把源站跑得更稳、更省资源、更少暴露面。

cloudflare-os 不是 Cloudflare 官方的操作系统,而是我面向自己的业务场景做的一套精简 Linux 镜像。它去掉了所有用不到的软件包,重新编译了内核,针对回源链路做了 TCP 栈和 TLS 优化,并且把根文件系统设计成只读模式。如果你也维护着多个源站、坐拥服务器权限但对默认系统的臃肿不满,那这篇文章里的思路和踩坑记录应该能帮你省下不少时间。

1. 为什么要再造一个轮子:云服务器默认系统的三个痛点

1.1 通用发行版的"过度服务"

大部分云厂商提供的基础镜像都是标准的 Ubuntu 或 Debian,装完后系统里有一堆我根本用不上的服务:ModemManager、apport、cups、snapd……这些服务吃内存倒是小事,真正麻烦的是它们扩大了攻击面。一台只用来跑 Web 服务的机器,根本不需要 DHCP 之外的网络管理工具,更不需要在对外暴露的端口上监听任何和业务无关的协议。

cloudflare-os 的第一步就是做减法:整个 rootfs 只保留系统运行的最小集合。没有包管理器,没有编译工具链,没有桌面,没有 X11,甚至没有常规的 syslog 服务。启动后你能看到的就是一个 busybox init、一个 Web 服务器进程、一个负责和 Cloudflare 边缘建立回源连接的 cloudflared 进程,以及一个健康检查的 shell 脚本。

可能有人会问,没有包管理器怎么装软件?我的答案是:不要装。镜像本身就是不可变交付物,新版本直接重新构建,部署时替换整个启动槽位。这是从不可变基础设施那套思路借来的,实际效果比“跑一台又装一堆东西”干净得多。

1.2 回源慢的根源往往在内核 TCP 栈

如果你给 Cloudflare 配置了“仅 Cloudflare”模式,真实用户请求会先打到边缘节点,再由边缘节点回源到你的服务器。这意味着源站收到的连接本质上是一个从 Cloudflare 边缘到源站的跨机房 TCP 流。这类连接的 RTT 通常比用户直连更稳定,但也更容易被默认内核参数拖后腿。

大多数 Linux 发行版默认的拥塞控制算法是 Cubic,它对传统局域网和普通公网表现不错,但在高带宽、中等丢包率的回源链路上,效果并不理想。Cubic 在发生丢包后的窗口恢复节奏偏保守,容易让回源吞吐出现“慢启动、猛掉窗”的锯齿状波动。换成 BBR 之后,发送速率会基于实时测量到的 RTT 和带宽估计值动态调整,同样的网络条件下吞吐和延迟都能明显改善。

除了拥塞控制,TCP 接收/发送缓冲区默认值也偏小。默认的 wmem 和 rmem 虽然支持自动调整,但在服务器侧处理大量短连接时,自动调整还没达到目标窗口,连接可能就已经结束了。cloudflare-os 的内核配置里直接放大了初始缓冲区,并且启用了 tcp_slow_start_after_idle=0,保证连接长时间空闲后,不用再从慢启动阶段重新爬升。这条参数对 keep-alive 长连接的回源场景非常关键。

1.3 安全补丁滞后与暴露面控制

通用发行版的安全更新依赖包管理器和运维人员的习惯。现实是很多人装完系统就忘了打补丁。cloudflare-os 的镜像发布流程把补丁这件事变成了“重建镜像 + 滚动重启实例”,不再依赖那台机器里的 apt update 或 yum update。

同时,只读根文件系统直接干掉了大量基于文件写入的入侵持久化手法。就算攻击者真的通过 Web 应用漏洞拿到了代码执行权限,他能写的只有 tmpfs 和内存里的临时目录,重启之后一切归零。配合 Cloudflare 的 WAF 托管规则和 Tunnel 方式回源,源站甚至可以做到不开放任何入站端口,只在出站方向主动连出到 Cloudflare 边缘。

这套组合拳打下来,给我最直观的感受是:系统日志里那种无差别扫描流量基本消失了,安全公告的焦虑也大大降低。因为我能被公网接触的端口只有 80/443,而且只允许 Cloudflare 边缘 IP 段访问,其他端口要么不监听,要么根本没在内核层开。

2. cloudflare-os 的核心设计与技术取舍

2.1 内核版本与编译裁剪策略

我选择 Linux 6.6 LTS 作为内核基线。原因很简单:长支持周期,且包含了足够的网络性能改进,例如对 BBRv2 的完善、更好的 XDP 支持,以及其他一些 TCP 调优选项。所有必要的驱动能编进内核就编进内核,不使用模块加载,启动时不再依赖 initramfs 去探测硬件。

内核裁剪也不是越激进越好。为了以后方便在边缘源站上做流量观测,我保留了 BPF 和 XDP 相关选项;为了支持只读根,保留了 overlayfs 和 squashfs;为了配合云厂商的虚拟化环境,保留了 virtio 全系列驱动和常见半虚拟化网卡驱动。关掉的是各类不需要的外设驱动、蓝牙、Wi-Fi、消费级音频视频框架。下面是我在 menuconfig 中重点调整的几个开关:

配置项值理由
CONFIG_TCP_CONG_BBRy回源链路高带宽高RTT下吞吐更稳
CONFIG_NET_SCH_FQyBBR推荐配合 fq 队列规则
CONFIG_TCP_CONG_ADVANCEDy允许切换可用拥塞控制算法
CONFIG_OVERLAY_FSy实现只读根+可写临时层的核心
CONFIG_SQUASHFSy根文件系统镜像格式,压缩率高
CONFIG_BINFMT_SCRIPTy支持脚本直接执行,方便启动 shell 脚本
CONFIG_DEVTMPFSy自动挂载 /dev,减少启动依赖
CONFIG_FW_LOADERy加载部分网卡固件所需
CONFIG_VIRTIO_*y云虚拟机必备驱动

裁掉模块加载后,整个内核镜像体积在 8MB 左右,启动速度从 Ubuntu 内核的十几秒降到三秒内,这部分收益在批量扩容和故障重启时非常明显。

2.2 网络栈调优参数语义

光有 BBR 还不够,sysctl 参数需要整体配合。cloudflare-os 的 /etc/sysctl.conf 是构建时就固化进镜像的,不运行时修改。我挑几个影响最大的解释一下:

net.ipv4.tcp_congestion_control = bbr net.core.default_qdisc = fq net.ipv4.tcp_slow_start_after_idle = 0 net.ipv4.tcp_mtu_probing = 1 net.ipv4.tcp_notsent_lowat = 16384 net.core.rmem_max = 134217728 net.core.wmem_max = 134217728 net.ipv4.tcp_rmem = 4096 87380 134217728 net.ipv4.tcp_wmem = 4096 16384 134217728 net.ipv4.tcp_fin_timeout = 15 net.ipv4.tcp_tw_reuse = 1 net.ipv4.ip_local_port_range = 1024 65535
  • tcp_slow_start_after_idle = 0:长连接空闲后再发包,不走慢启动。对 WebSocket 或持久连接特别友好。
  • tcp_notsent_lowat = 16384:在较高的 BDP 环境下,降低单连接内未发送数据量的阈值,本质上让任务队列的调度更偏向低延迟。
  • tcp_rmem和tcp_wmem第三项直接给到 128MB:允许吞吐跑得更高,尤其是在多线程下载或大文件回源场景下。
  • tcp_tw_reuse = 1:源站作为客户端与 Cloudflare 边缘通信时,TIME_WAIT 连接可以被安全复用,避免大量短连接时端口耗尽。

注意,这些参数不是越高越好。我曾经把 wmem_max 调成 256MB,结果在某些高峰期反而因为内存占用过高出现 swap 抖动。对于 4GB 内存的源站,128MB 已经是安全边际。

2.3 TLS 加速与会话复用的内置方案

源站和 Cloudflare 边缘之间的回源连接通常走 TLS 1.3,证书在 Cloudflare 面板配置。为了让 TLS 握手尽量快,cloudflare-os 里内置了 Caddy 作为默认 Web 服务器,配置上强制 TLS 1.3,并开启会话票据缓存。

{ auto_https off servers { protocols h1 h2 } } :80 { route { redir https://{host}{uri} permanent } } :443 { tls /etc/ssl/fullchain.pem /etc/ssl/privkey.pem { protocols tls1.3 alpn h2 http/1.1 } handle { reverse_proxy 127.0.0.1:8080 } }

这里的关键点是auto_https off和手动指定证书文件。如果 Caddy 默认开启自动 HTTPS,它自己会去找 CA 签发证书,但源站证书本来就由 Cloudflare 管理。手动配好后,Caddy 不会干预 Cloudflare 的证书轮换机制。

会话复用的意义在于,从 Cloudflare 边缘到源站的连接如果可以做 TLS 握手复用,回源耗时可以减少一次完整的 TLS 密钥协商。实测下来,在长连接被 Redis 等中间件斩断的场景下,这个优化能稳定降低几十毫秒的重复握手开销。

2.4 只读根文件系统与原子更新

这是 cloudflare-os 最与众不同的设计:根文件系统是 squashfs 只读镜像,启动时通过 overlayfs 挂一个 tmpfs 作为可写层。应用想写 /etc 或 /var 里的东西,只会写到内存中,重启即消失。

更新流程也很简单:构建新镜像文件,写到磁盘的另一个槽位,修改引导参数指向新槽位,然后重启。如果新版本有问题,重启时切回旧槽位就完成了回滚,不存在“改了一半系统”的状态。

在实现上,我会用 grub 的双 entry 做启动槽位切换,或者用 UEFI 的 boot 顺序控制。配合系统自带的 watchdog,如果健康检查连续失败,自动重启到上一个镜像槽位。这套机制上线后,我已经完全不怕配置改挂这种事了。

当然,只读根也不是没代价。最大的代价是任何需要持久化的状态都得提前规划:比如证书文件、nginx 日志、cloudflared 的 token。我的做法是单独挂载一块小容量 SSD 到 /data,日志也通过 /data 重定向出去,镜像本身保持绝对的“一次性”。

3. 完整构建过程:从零到可启动镜像

3.1 构建环境与基础组件

构建 cloudflare-os 我用的是一台普通 Debian 12 虚拟机,依赖非常基础:make、gcc、flex、bison、bc、libssl-dev、libelf-dev、rsync、cpio、squashfs-tools。核心工具是 Buildroot,它能把交叉编译和外置软件包的集成简化很多。

目录结构大概长这样:

cloudflare-os/ ├── buildroot/ ├── board/ │ └── cfos/ │ ├── rootfs-overlay/ │ ├── patches/ │ └── cfos_defconfig ├── packages/ │ └── cloudflared/ └── scripts/ ├── build-kernel.sh ├── build-rootfs.sh └── make-uefi.sh

Buildroot 的好处是它自带大量软件包,并且所有包都作为一个整体 rootfs 被构建出来,生成的产物就是一个完整的可启动镜像。不适配的软件包可以通过外部自定义 package 机制加入,cloudflared 我就用这种方法打进去。

3.2 内核配置关键项

为了方便复现,我不直接手动改 .config,而是把裁剪好的配置存成 cfos_defconfig,每次构建时把它作为基础,再追加少量配置片段。

cd buildroot make cfos_defconfig make linux-reconfigure

在 kernel 配置里,除了前面提到的 BBR、overlayfs、squashfs 之外,还有一个容易忽略但很重要的点:需要保留 cpufreq 调控器的内置支持。很多云服务器启动后如果 CPU 默认处于省电模式,回源延迟会出现周期性波动,编译时把性能调控器设为默认会稳定很多。

另外,如果你用的是 cloud 虚拟机,不要把无关的 SATA/AHCI 选项关掉,虚拟化平台对磁盘的模拟方式很杂,我这里吃过亏,后面踩坑部分会详细说。

3.3 生成 rootfs 与启动镜像

Buildroot 的配置我用了 slightly 定制过的 defconfig,关键项如下:

BR2_x86_64=y BR2_TOOLCHAIN_BUILDROOT_GLIBC=y BR2_ROOTFS_OVERLAY="board/cfos/rootfs-overlay" BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_CUSTOM_VERSION=y BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.30" BR2_LINUX_KERNEL_DEFCONFIG="cfos" BR2_TARGET_ROOTFS_SQUASHFS=y BR2_TARGET_ROOTFS_SQUASHFS_4K=y BR2_PACKAGE_CA_CERTIFICATES=y BR2_PACKAGE_OPENSSL=y BR2_PACKAGE_LIBCURL=y BR2_PACKAGE_CHRONY=y

rootfs-overlay 目录里放的是自建脚本和配置文件。启动流程是:squashfs 被内核挂载后,init 脚本先把必要目录 bind mount 好,然后启动 cloudflared 和 Web 服务器。

# board/cfos/rootfs-overlay/etc/init.d/S50cfos #!/bin/sh # 等待网络就绪 for i in $(seq 1 30); do ip route get 1.1.1.1 >/dev/null 2>&1 && break sleep 1 done # 加载证书信息 mount -t tmpfs tmpfs /etc/ssl # 从 /data 导入证书 cp -f /data/certs/fullchain.pem /etc/ssl/ 2>/dev/null cp -f /data/certs/privkey.pem /etc/ssl/ 2>/dev/null # 启动 cloudflared /usr/bin/cloudflared tunnel --config /data/cloudflared.yml & # 启动 Caddy /usr/bin/caddy run --config /etc/caddy/Caddyfile &

有朋友问为什么要先把 /etc/ssl 挂成 tmpfs。因为只读根上不能写证书,而证书会轮换,所以我在启动时从 /data 拷贝一份到内存中,保证使用的时候没有写权限问题。重启后证书重新加载一次,逻辑非常简洁。

3.4 集成 cloudflared 与监控组件

Buildroot 默认没有 cloudflared 包,我自己写了一个外部包定义。做法是下载官方编译好的 deb 包,在 Buildroot 的构建阶段解压,把里面的二进制拷贝到 target 的 /usr/bin 下。

# packages/cloudflared/cloudflared.mk CLOUDFLARED_VERSION = 2024.6.0 CLOUDFLARED_SOURCE = cloudflared-linux-amd64.deb CLOUDFLARED_SITE = https://github.com/cloudflare/cloudflared/releases/download/$(CLOUDFLARED_VERSION) CLOUDFLARED_STRIP_COMPONENTS = 0 define CLOUDFLARED_INSTALL_TARGET_CMDS mkdir -p $(TARGET_DIR)/usr/bin dpkg-deb -x $(DL_DIR)/$(CLOUDFLARED_SOURCE) $(@D)/dpkg cp $(@D)/dpkg/usr/bin/cloudflared $(TARGET_DIR)/usr/bin/cloudflared endef

监控那块我做得比较轻。系统里跑了一个 30 秒周期的脚本,依次检查:本地 Web 端口是否可访问、cloudflared 进程是否还存在、以及一个从 Cloudflare 边缘打过来的 HTTP ping 路径。脚本失败一次就记录到内存日志,连续失败三次触发重启。

这个轻量监控的好处是不需要 prometheus-node-exporter 这类重组件,精简系统就只干精简的事。如果你需要更复杂的指标,可以单独在 /data 挂载目录跑 agent,但不会进系统镜像。

4. 真实部署与对比数据

4.1 部署拓扑与迁移方式

我这里的源站全部在云上,前面套了 Cloudflare 免费版,配置采用的是 Full (Strict) SSL 模式。迁移前是腾讯云/阿里云 Ubuntu 22.04 默认环境加宝塔面板,迁移后直接替换成 cloudflare-os。

对于 cloudflared 的接入,我选择了 Cloudflare Tunnel 模式,这样源站完全不需要对外暴露 80/443 端口,防火墙策略可以收紧到只允许来自边缘节点的出站连接。cloudflared 进程主动向 Cloudflare 边缘建立连接,然后边缘把请求通过这条连接转发到本地 Web 服务。

这类架构还有个别的好处:换 IP 不会影响站点访问,因为公网 IP 压根没有对外开放。所有域名流量都通过 Cloudflare 的边缘网络分发,我这边只需要保证 cloudflared 的连接是健壮的即可。

4.2 性能实测:TLS 握手、TTFB、吞吐

部署完成后,我对同样一台同样配置的机器做了 A/B 测试。机器规格是 2 核 4G,SSD 系统盘,源站在广州区域,Cloudflare 回源路径从香港或东京过来的延迟大概 60ms 到 120ms。我实测的一批数据如下:

指标Ubuntu 22.04 默认cloudflare-os提升
内存空闲2.1GB 可用3.6GB 可用明显
启动时间15s2.8s81% 快
TLS1.3 回源握手(平均)78ms42ms46% 快
TTFB(动态 API 请求)162ms119ms26% 快
单核 HTTP 吞吐(wrk -t1 -c100)1.4w req/s1.9w req/s35% 高
内存占用(空闲)892MB178MB降低

注意,这里的 TTFB 提升不完全来自内核参数,Caddy 比宝塔那套 Nginx + PHP-FPM 的默认配置更轻量,也贡献了一部分。但 TLS 握手时间的下降确实主要靠 BBR 和 sysctl 优化。

4.3 运维习惯的变化

没有 SSH 之后,我一开始还有点慌,后来发现日常运维反而更顺了。因为我根本不需要登录进系统“修修补补”,所有变更都通过 Git 仓库构建镜像,然后一键发布。

真正要进控制台排查问题时,我用的是云厂商的 VNC 控制台,mount 上持久化分区翻看日志。由于系统本身是只读的,VNC 里能看到的东西非常有限,但这正好逼着我从应用日志和 Cloudflare 的访问日志里去定位问题,而不是动不动就上机器 apt install 然后一顿乱调试。

这种“逼你少动生产环境”的机制,长期来看是一种保护。我日常发布频率不高,每周大概一两次,每次都是重建镜像加滚动重启,运维压力反而比传统方式小很多。

5. 踩坑记录:最耗时的三个问题及排查链路

5.1 问题一:网卡驱动固件缺失导致高延迟抖动

第一次部署到某云平台后,外网连通性倒是正常,但回源延迟每隔几十秒就会出现一次 200ms 以上的尖峰。这个问题并不是每次都能复现,所以一开始我怀疑是网络线路抖动,看了 Cloudflare 的边缘日志也没发现明显异常。

后来我直接登录 VNC 控制台,执行dmesg -T发现一串关于 e1000e 网卡固件加载失败的报错。原因是我裁剪内核时为了省体积,把 firmware 库一起裁掉了,而该云平台的虚拟化环境正好模拟了需要额外固件的网卡型号。没有固件的网卡虽然能通,但会周期性停止发送数据来等待固件重载,于是产生尖峰。

解决方案很简单:把对应的固件文件拷进 rootfs-overlay 的 /lib/firmware 目录,重新构建镜像。但在那之前,我靠ethtool -S看到的 tx_timeout 计数才确认是网卡层面问题,而不是内核 TCP 参数问题。这个教训是:裁剪内核时需要把网卡固件单独归类保留,不能只看 CONFIG 开关。

5.2 问题二:systemd-journald 持续写盘拖垮只读根

cloudflare-os 不用 systemd,但我在某个配置分支里想偷懒试运行 systemd,结果 journald 一直往内存 tmpfs 里写日志,短时间内 tmpfs 被写满,然后整个系统发生连锁故障。其实问题本质不在于 systemd,而在于我没有为日志设置上限。

后来即使不用 systemd,busybox 的 syslogd 也会把日志写到 /var/log/messages,而 /var 如果不在只读层就在 tmpfs。我给 /data 单独划了块持久分区,然后把日志输出重定向到 /data/logs,syslogd 的配置文件改成轮转每天一份,保留 7 天。这样日志不会写爆内存,也不会污染只读根。

dmesg是老朋友,但有些系统服务自己的日志不会进内核。我在 cloudflared 的启动命令里加了--logfile /data/logs/cloudflared.log,这个问题很快就定位到了。

5.3 问题三:cloudflared 证书轮换与系统时钟跳变

最隐秘的一个坑是:镜像里没有默认同步时间,而云主机开机时的硬件时钟往往和真实时间差几十秒甚至几分钟。cloudflared 在和 Cloudflare 边缘建立连接时,会校验客户端证书的有效时间窗口。系统时间一旦超前太多,握手直接失败。

首次出现该问题是某次机器因维护被强制停机再开机后,服务一直无法恢复。我 VNC 进去看进程还在,但 cloudflared 日志里全是证书过期错误。查了半天才想到是硬件时钟不正确。

解决方法是内置 chrony 服务,启动脚本里强制等待chronyd同步一次再拉起 cloudflared。同时我在构建镜像时用hwclock --systohc把时间基准写进 RTC。这一改动之后,再也没遇到过因时间偏移导致 tunnel 断开的问题。

如果你也要做类似系统,建议把时间同步放到启动链最前面。等待过程可能多花两三秒,但远比连接失败后人工介入要省事。

6. 关于这套系统,我的最终评价和可扩展方向

cloudflare-os 的真正价值不在于“精简系统本身”,而在于它把源站部署的模糊状态变成了一种可复现、可回滚、可审计的交付物。任何一台机器只要刷入相同的镜像,行为完全一致;出问题也不需要 SSH 上去“碰运气”,直接切槽位就能恢复。

目前我还在往几个方向扩展这套系统:一是用 Cloudflare Workers 做一层更细的健康探测,把故障隔离做得更主动;二是在内核里加入更多 eBPF 观测点,用来追踪回源连接的真实时延分布;三是研究如何把 /data 分区也做成版本化快照,让日志和证书状态也能快速回退。

如果你也想尝试类似方案,我建议从最小的业务先试验起,不要一上来就把核心库全部迁过去。先用一台非关键源站测试镜像构建、连接稳定性、更新回滚这三个最基础环节,再逐步扩大范围。踩过一轮坑之后,你会理解为什么很多基础设施团队会对“不可变基础架构”这件事越来越上瘾——它确实让系统变得更好睡了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 13:01:31

CentOS 7.7用户账号管理与安全配置详解

1. CentOS 7.7账号管理基础架构解析在RHEL系Linux发行版中,用户账号体系采用分层设计架构。/etc/passwd文件存储基础用户信息,包含7个字段的冒号分隔记录。以典型条目ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin为例:字段1:用户…

作者头像 李华
网站建设 2026/10/28 13:01:29

基于声学特征提取的辨音识键系统设计与实现

简介:这份PDF是2023年全国大学生电子设计竞赛高职高专组K题「辨音识键奏乐系统」的完整赛题文档,面向备赛的专科与本科参赛队及指导教师,帮助读者快速掌握题目任务、技术指标与评分细则。文档完整给出基本要求与发挥部分:一键自动…

作者头像 李华
网站建设 2026/10/28 13:00:26

混合遗传算法求解带体积约束的装配线平衡问题

简介:面向运筹优化与制造系统方向的学习者,这份资源提供装配生产线任务平衡问题(ALB)的遗传算法MATLAB实现,适合已具备一定MATLAB编程基础、希望理解智能优化算法如何落地到产线工位分配场景的读者。算法以陈永卿等《基…

作者头像 李华
网站建设 2026/10/28 12:58:51

边缘智能技术解析:挑战、解决方案与实战案例

1. 边缘智能的本质与行业驱动力边缘智能(Edge AI)正在重塑人工智能的落地方式。与传统的云端AI处理不同,边缘智能将计算能力下沉到数据产生源头,在摄像头、传感器、工业设备等终端直接完成AI推理。这种模式最显著的优势是实现了毫…

作者头像 李华
网站建设 2026/10/28 12:58:37

ECC双线拆解:P-384证书体系与SAP LSMW批量导入实操

1. 从"ECC"这三个字母说起:它到底指什么第一次看到"ECC"这个标题,很多人会愣一下——这三个字母在不同圈子里指向完全不同的东西。做密码学的会想到椭圆曲线密码学(Elliptic Curve Cryptography),…

作者头像 李华
网站建设 2026/10/28 12:58:18

照片EXIF经纬度写入指南:无GPS相机如何批量补坐标

很多人第一次意识到照片能带坐标,是在整理旅行相册的时候:手机拍的图在地图上密密麻麻排成一条线,而相机拍的那几百张却像被扔进了黑洞,只能靠文件名和记忆去猜是在哪儿按的快门。还有一类人反过来——做外业记录、房屋勘察、门店…

作者头像 李华