<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Tech Philosopher</title>
    <link>https://blog.bktus.com/</link>
    <description>Recent content on Tech Philosopher</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sat, 23 May 2026 00:35:00 +0200</lastBuildDate>
    <atom:link href="https://blog.bktus.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>搭建一个可分流的个人VPN网关：WireGuard、sing-box与Gluetun的组合实践</title>
      <link>https://blog.bktus.com/archives/vr4bm4/</link>
      <pubDate>Sat, 23 May 2026 00:35:00 +0200</pubDate>
      <guid>https://blog.bktus.com/archives/vr4bm4/</guid>
      <description>&lt;p&gt;在&lt;a href=&#34;https://blog.bktus.com/archives/ozzkto/&#34;&gt;之前的文章&lt;/a&gt;中，我介绍过一种比较直接
的链式 VPN 方案：所有设备先连接到自己搭建的WireGuard 服务器，再由服务器把流量转
发到 Gluetun，最终通过上游 VPN 服务商的出口访问互联网。&lt;/p&gt;
&lt;p&gt;这个方案的核心价值很明确：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;所有设备只需要配置一个 WireGuard；&lt;/li&gt;
&lt;li&gt;上游 VPN 只需要在服务器端维护；&lt;/li&gt;
&lt;li&gt;可以把手机、电脑、平板、家用设备统一接入同一个虚拟局域网；&lt;/li&gt;
&lt;li&gt;出口 IP 由商业 VPN、公司 VPN 或其他上游 VPN 提供，而不是直接暴露 VPS IP；&lt;/li&gt;
&lt;li&gt;整套系统可以通过 Docker 部署，尽量不污染宿主机环境。&lt;/li&gt;
&lt;li&gt;相比于直连VPN，该方案下VPN服务商能看到的只是你的VPN网关出口（你的VPS服务
器），而不是每个设备的真实 IP。&lt;/li&gt;
&lt;li&gt;另外，本地的ISP等也看不到你是否是在使用主流VPN，因为他们只能知道你在连接到一个
VPN网关（你的VPS服务器），但流量最终去了哪里是未知的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不过，随着使用场景变多，原来的结构也逐渐暴露出一些局限。最典型的问题是，对流量的
控制不够细粒度。默认情况下所有流量都必须进入上游 VPN 隧道，这对于某些服务可能会
触发风控，或者导致访问问题。而且比较难方便地进行流量工程，对不同服务采用不同的出
口策略。原先通过 iptables 和路由表的方式虽然能实现分流，但规则一多就难维护。&lt;/p&gt;
&lt;p&gt;因此，我把原来的方案重新整理成了一个更完整的个人 VPN 网关架构。新版方案不再只是
简单的 &lt;code&gt;WG-Easy + Gluetun&lt;/code&gt;，而是变成了：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WG-Easy + sing-box + Gluetun + AdGuard Home + config.yaml 统一配置生成
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对我来说，这套方案已经不只是“VPN 套 VPN”，而是一个可以长期维护、可扩展、可观察的
个人网络出口。它既可以服务日常上网，也可以服务远程办公、家庭内网访问、开发测试和
多设备统一管理。如果你只需要最简单的全局 VPN 转发，旧版思路仍然够用。但如果你希
望在隐私、可控性、分流规则和 DNS 管理之间取得更好的平衡，新版架构会更合适。&lt;/p&gt;</description>
    </item>
    <item>
      <title>个人 VPS 自部署的长期主义：干净与安全</title>
      <link>https://blog.bktus.com/archives/6upskf/</link>
      <pubDate>Fri, 02 Jan 2026 23:20:27 +0000</pubDate>
      <guid>https://blog.bktus.com/archives/6upskf/</guid>
      <description>&lt;p&gt;我开始认真折腾个人 self-host，大概已经有五六年了。严格意义上开始管理我自己的 VPS
的时间点，应该还可以往前追溯。最初的动机其实很简单：有些服务我每天都在用，比如密
码管理器、音乐播放、笔记同步、个人网站、代码仓库等等。既然如此，为什么不干脆自己
部署？这样一来数据在自己手里，也不用被各种平台订阅和涨价牵着走。&lt;/p&gt;
&lt;p&gt;这几年一路走下来，说实话，self-host 并不省心。我要维护系统、备份数据、关心安全、
偶尔还要救火。但它给我的回报也很明确：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据完全掌控在自己手里&lt;/li&gt;
&lt;li&gt;不再被订阅价格牵着走&lt;/li&gt;
&lt;li&gt;对系统、网络和安全的理解明显更深&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现在我一台服务器跑着十几个服务，成本只是一台服务器的钱。在这两年取消了不少第三方
平台的订阅后，算下来，整体成本可能反而更低。对我来说，这种“复杂但可控”的状态，反
而比依赖一堆外部服务更安心。当然不这适合所有人，我感觉有：有一定技术背景的人、喜
欢折腾的人以及愿意为稳定与掌控付出时间的人，这三者合一就适合这样。&lt;/p&gt;
&lt;p&gt;到现在，我并不觉得自己成了什么“专家”，但有到现在两件事的感受越来越强烈：&lt;strong&gt;安全性
&lt;strong&gt;以及&lt;/strong&gt;服务器环境的整洁程度&lt;/strong&gt;，这也是这篇文章的两个主线。这两个问题，几乎决定了
你这台服务器上的各类服务能不能长期稳定地用下去。然后就是需要迁移的时候，比如换了
一个更便宜或者更好的 VPS 供应商，这个时候的工作量（我自己就换了好几次，知道真的
换不动了才稳定下来）。&lt;/p&gt;
&lt;h2 id=&#34;草莽阶段&#34;&gt;草莽阶段&lt;/h2&gt;
&lt;p&gt;最开始的时候，我的做法非常朴素。我会直接在宿主机上安装服务，然后安装 Nginx 或者
Apache2（httpd）。比如用 Nginx 做反向代理，Nginx 这类 Web 服务器 的好处是配置文
件可以拆开，每个站点一份，用域名来区分各个服务而不是端口号，看起来井井有条。那时
候我觉得这套方案挺优雅的。&lt;/p&gt;
&lt;p&gt;但随着服务慢慢变多，问题开始一点点浮现。有的服务需要特定版本的依赖，我很难在同一
个环境安装不同版本的各种依赖库或者数据库。而有的会在系统里留下各种临时文件；配置
文件散落在 &lt;code&gt;/etc&lt;/code&gt;、数据放在 &lt;code&gt;/srv&lt;/code&gt;，日志又在 &lt;code&gt;/var&lt;/code&gt;。一开始你还能记得“这是哪个服
务的”，时间一长就完全混在一起了。&lt;/p&gt;
&lt;p&gt;这期间，当我想删除一个不用的服务时，我已经不敢确定自己删得干不干净。特别是有的服
务提供“一键安装脚本”，安装的时候一时畅快，等到了你想摆脱它的时候，你会发现当初的
脚本不知道做了什么改动，如何复原都毫无头绪。你很难确认还有没有残留的配置、后台进
程，甚至不知道删错东西会不会影响别的服务。这种不确定感，本身就是一个风险，对于强
迫症来说，每每想起简直是如鲠在喉。&lt;/p&gt;
&lt;h2 id=&#34;容器化阶段&#34;&gt;容器化阶段&lt;/h2&gt;
&lt;p&gt;后来我把几乎所有服务都迁移到了 Docker 里。而且，到现在越来越倾向于将所有能用的到
的服务或者工具软件容器化，再去部署。有些不提供标准的容器化部署方案的，但又很想用
的服务，我会直接自己进行容器化包装，形成自己的容器化的解决方案。&lt;/p&gt;
&lt;p&gt;真正改变体验的不是 Docker 本身，而是 &lt;strong&gt;Docker Compose&lt;/strong&gt;。容器这东西，本质上就不
应该被当成“长期维护对象”，它随时都可以被删掉、重建，你需要意识到这个。早期的时
候，我觉得 Docker Compose 配置文件麻烦，为什么不用命令直接创建一个容器，然后让这
个容器长期运行。后来等我要更新，或者这个服务依赖多个底层的其他容器的时候，问题就
逐渐浮现出来。如果当初将对服务的部署写下来，写到一个配置文件中，然后每次就执行这
个配置文件就能完美复现原先的部署，不需要自己额外配置什么 Bridge 网络，或者什么
hostname，亦或者是重启策略。这个节省了大量的时间和精力，并且配置的时候出错的可能
性，也大大降低了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>GpgFrontend的前世今生：我与一个开源加密工具的成长之路</title>
      <link>https://blog.bktus.com/archives/5l9c2j/</link>
      <pubDate>Wed, 12 Nov 2025 22:21:17 +0100</pubDate>
      <guid>https://blog.bktus.com/archives/5l9c2j/</guid>
      <description>&lt;h2 id=&#34;缘起偶遇-gnupggpg&#34;&gt;缘起：偶遇 GnuPG（GPG）&lt;/h2&gt;
&lt;p&gt;我在 2021 年 4 月左右第一次接触 GPG。那时我还只是个对计算机世界充满好奇的学生，
对密码学的理解也仅停留在“密码就是加密字符串”这样的表层概念。但当我第一次读到非对
称加密的原理——&lt;strong&gt;一个公钥可以让所有人加密信息，而只有私钥拥有者才能解密&lt;/strong&gt;——我被深
深震撼了。这种“数学意义上的信任”让我着迷。它优雅、严谨、不可逆。那一刻，我意识
到，这种技术的美感并不亚于任何艺术创作。于是我开始学习 GPG 命令行的各种操作，从
密钥生成到签名验证，反复实验，琢磨其中的逻辑。&lt;/p&gt;
&lt;p&gt;但与此同时，我也发现了问题：**命令行的门槛实在太高。**特别是有的时候，想快点做一
些简单操作却要输入一串命令，让我感觉“不爽”。对非技术用户来说，GPG 的命令行是一片
晦涩的荒原，几乎挡住了所有想尝试的人。我开始想，如果能为 GPG 做一个简单易用的图
形界面，让它像一台看得见摸得着的“密码机机”那样可视化与便捷；如果每个人都可以简单
地拥有者与一台耐用且小巧的“密码机”，也许会有更多人愿意尝试。这个想法当时看起来微
不足道，但正是它，开启了我后来整整数年的技术旅程。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“密码机”让人立刻联想到某种坚固、可靠的小设备，就像早期的机械密码机（如
Enigma）那样充满仪式感。它承载的不仅是技术，更是一种对安全的信念。这种机器功能
不求繁多，却必须精准可靠。用户按下一个按钮，期望它执行的动作必须**可预期且安全
**。这种对“可控性”的追求，就是“密码机”的灵魂。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;我开始寻找现成的解决方案。那个时候已经有一些 GUI 工具，比如 Kleopatra。但它们的
很多都界面复杂、功能太多，甚至还引入了 X.509 证书体系，这在当时一下子劝退了我。
我希望的是一个更轻、更纯粹的东西。后来我发现了一个叫
&lt;a href=&#34;https://git.bktus.com/gpgfrontend/gpg4usb/&#34;&gt;&lt;strong&gt;gpg4usb&lt;/strong&gt;&lt;/a&gt; 的项目，它非常接近我理
想中的形态——轻量、可携带、跨平台。然而遗憾的是，它早已停止更新，只支持 GPG 1.4
版本。那意味着它与现代系统的兼容性问题几乎无法回避，也无法支持子密钥机制。&lt;/p&gt;
&lt;p&gt;我开始琢磨：**能不能在它的基础上重写一部分，让它重新焕发生命？**在 5 月份左右，
我花了大约半个月的时间，在宿舍里读它的源码，摸索 GPG 的接口调用方式，研究 Qt 框
架与跨平台兼容。那是一个孤独却极其充实的过程。每当我让一个新功能成功运行时，心里
的成就感都难以言喻。当我终于让它在 GPG2 环境下运行起来，并修复了不少原有的 Bug
后，我决定给这个焕然一新的项目一个新名
字：&lt;a href=&#34;https://gpgfrontend.bktus.com/&#34;&gt;&lt;strong&gt;GpgFrontend&lt;/strong&gt;&lt;/a&gt;——GPG 的图形前端，也是我人
生中的第一个完整开源项目。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;GpgFrontend&#34; loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2025/11/13/6c111b21bb6d134d72fbf356f5f0d8c520115f13-1.webp&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;亮相从宿舍代码到-github-上的光点&#34;&gt;亮相：从宿舍代码到 GitHub 上的光点&lt;/h2&gt;
&lt;p&gt;我将第一个版本上传到 GitHub 后，并没有期待太多关注。毕竟这是个极小众的领域，GPG
本身就不是大众常用的东西。但几天后，我收到了第一个 issue。那是一位用户，提到程序
在某个操作系统上无法运行。他不仅提供了日志，还提出了修改建议。那一刻，我第一次感
受到某种力量，愿意继续为这一个项目投入时间。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年四月第二周技术周报</title>
      <link>https://blog.bktus.com/archives/0ee6o6/</link>
      <pubDate>Mon, 10 Nov 2025 21:38:26 +0100</pubDate>
      <guid>https://blog.bktus.com/archives/0ee6o6/</guid>
      <description>&lt;p&gt;&lt;strong&gt;原文经过 AI 润色，非本人文风。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在全国范围（如广州、深圳、上海、北京）部署大量客户端的配置下发服务中，面对节假
日、活动上线等高并发场景，传统的单地数据中心架构难以支撑。本文分享我当属在“配置
下发服务”层面进行的多地部署、数据层优化及缓存机制升级，阐述其技术背景、方案设
计、落地实践与收获。&lt;/p&gt;
&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;
&lt;p&gt;我服务的客户端分布在广州、深圳、上海、北京等全国多个城市，通常需要根据运营策略获
取各种动态或静态配置，比如节日活动、功能开关、故障临时屏蔽等。这些配置由服务端统
一下发，客户端根据自身属性（地域、版本等）拉取对应内容。&lt;/p&gt;
&lt;p&gt;随着客户端规模扩大，特别是在活动上线、客户端批量启动的场景中，配置拉取请求会在短
时间内剧增，导致服务端QPS暴涨，严重时甚至会拖垮主服务节点。我虽在容器层实现了全
国多地的 Kubernetes Workload 部署，但数据层（包括数据库和 Redis）仍集中在广州。
所有请求即便从北京或成都的容器发出，最终还是要跨地域访问广州的数据中心，延迟高、
压力集中、体验差。&lt;/p&gt;
&lt;p&gt;此外，虽然服务中使用了容器内缓存机制，但考虑到容器本身应保持无状态，其运行内存不
适合长时间、海量地持有配置缓存。一旦配置数据规模扩大至几百兆甚至上 GB 级别，运维
和资源成本都急剧上升。&lt;/p&gt;
&lt;p&gt;为了解决这些问题，我决定从数据层和缓存层入手，进行更彻底的多地部署改造。&lt;/p&gt;
&lt;h2 id=&#34;设计思路&#34;&gt;设计思路&lt;/h2&gt;
&lt;p&gt;基于上述挑战，我设计的方案主要包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;主数据库实例（写 + 读）部署在广州&lt;/strong&gt;，运营人员在这个实例上进行配置管理、写入
操作。&lt;/li&gt;
&lt;li&gt;各地部署 &lt;strong&gt;只读副本（Read‑Only）数据库实例&lt;/strong&gt;，例如上海、北京、成都等地。各地
容器连接对应地区的只读实例以拉取配置。&lt;/li&gt;
&lt;li&gt;Redis 亦做多地部署：每个地域有自己的 Redis 实例，容器拉取缓存优先从本地
Redis；若缓存未命中，再访问本地只读数据库或主数据库。&lt;/li&gt;
&lt;li&gt;在配置下发平台中，对不同 Kubernetes Workload 打标签（如地域、版本、标签等），
客户端根据标签拉取对应配置。运营人员仍在统一平台管理配置。配置平台写入主数据
库，然后同步至只读副本，各地容器读取对应地域的副本。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;架构优势&#34;&gt;架构优势&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;读请求分散到各地只读副本，减轻主数据库压力。&lt;/li&gt;
&lt;li&gt;客户端拉配置网络路径变短、延迟下降、体验提升。&lt;/li&gt;
&lt;li&gt;配置写入集中在主实例，确保配置管理统一、操作简便。&lt;/li&gt;
&lt;li&gt;架构符合“写少、读多”的典型场景：操作多为配置读取，写入（新增活动、屏蔽功能等）
相对少。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;实施&#34;&gt;实施&lt;/h3&gt;
&lt;p&gt;根据上面的设计，我继续保留广州作为主写中心，同时在全国多个区域（如北京、上海、成
都）部署只读副本，配合就近的 Redis 实例，实现配置服务的分布式读请求调度。主数据
库仍由运营人员维护和写入更新，通过异步同步机制，将数据分发到各地只读副本。各地的
容器服务则连接本地副本，从而避免跨地域拉取配置数据。&lt;/p&gt;
&lt;p&gt;Redis 也采用相似策略，在每个部署地域都设立实例，服务端优先从 Redis 缓存中获取所
需配置，未命中时才回源数据库。这样既减轻数据库压力，也提升了配置拉取效率。为了让
客户端能快速命中就近服务节点，我基于 DNS 做了地域级别的接入调度，同时结合
Kubernetes Workload 的标签机制，自动下发对应配置。所有运营配置仍在部署在广州的
“统一平台”进行集中管理，通过主数据库推送同步，容器按标签识别自身身份，拉取所需数
据。&lt;/p&gt;</description>
    </item>
    <item>
      <title>先行动而非先推理</title>
      <link>https://blog.bktus.com/archives/0jriuh/</link>
      <pubDate>Mon, 10 Nov 2025 19:30:00 +0100</pubDate>
      <guid>https://blog.bktus.com/archives/0jriuh/</guid>
      <description>&lt;p&gt;很多时候，我在做事前都会去考虑很久利弊得失。就比如：我去做了这件事会遇到哪些情
况？这些情况下我该怎么办？那些情况下会不如人意？我用的这些个方法真的好吗？等等。
不得不说，这伴随了我的很多的决策，特别是在一些比较大的决策下，这些事先的思考真的
有用处。所以，我在做很多事情之前，都会去想一下这些问题。如果我的结论是：这件事情
目前条件不成熟，或者这件事情很麻烦，亦或者这件事情目前前置条件没达到。那么我就不
会去做这件事情，以免投入了很多，却收效甚微。但是，最近我就发现，我这样将这个方法
扩大化并不好。因为很多事情，对我来说是新的，在我现有的经历和经验下，对这些事情的
认知还处于比较幼稚的阶段。这种情况下，我无法正确地去推理上面说的这些问题，从而去
得出正确的结论。&lt;/p&gt;
&lt;p&gt;具体来说，利用常识是真的能枚举一些可以预见的情况的，理论上，这些情况会发生。但
是，实际上，一件事情，或者一个项目，这些理论上会发生的事情都有它们会发生的概率。
这些概率又由许许多多的前置变量决定，如果对这件事情的认知不足，很难说对这些变量抓
大放小，找出主要。这样就容易放大一些变量的影响，最终导致预测的事情其实并不会发
生。另外，在很多情况下，我也会对一件事物的性质和反应对出某种推断，特别是对一类人
的推断，比如说我觉得某些人不友善，某些人友善这样。但实际上，在你真正地接触这些人
后，你才能知道他们是否真如你想得那样友善。或者说，他们对于你和他们接触的真正反
应，只有你去接触后才知道。这些事情是无法进行预先推断的，除非建立在你经常和别人打
交道的基础上。所以，在很多时候，我对于某些事物，某些人群的判断，是先入为主的，是
从别人那里听来的，模糊的，加入了自己想象的一种判断。大多数时候，这些判断并不准
确。如果我想让这些判断准确，那么我就要先行动起来，去做这些事情。&lt;/p&gt;
&lt;p&gt;先行动，也就是说在对事情有个轮廓，模糊的前提下，优先行动起来，放低姿态去尝试，然
后再根据反馈的结果看看是否可行。如果反馈良好，完全可以继续行动。如果反馈不好，也
不必立即收手，可以分析一下原因，或者拿着这些具体的案例问问其他过来人。不论哪一种
情况，都比先不动，然后想一大堆，这样如何那样如何，来得具体、实在与真切。很多我们
认为实践中会遇到的比较大的问题，往往会在真正的实践中找到思路。反之，在实践中真正
遇到的大的问题，在想法中往往预料不到。所以，先激活自己，去迈出第一步，在对事情认
知比较模糊的情况下，比什么都重要。&lt;/p&gt;
&lt;p&gt;先推理，我认为是建立在对事情已经有一个比较成熟的把握的情况下，特别是在这个事情所
述的领域，我并不是一个纯粹的新手。而推理的准确度，建立在我在这个领域的学习与实践
的成果的叠加。也就是说，推理需要真真切切的样本，这些样本需要自己得到，而不是纯粹
从别人那里“听来”，更重要地是自己通过实践“寻来”。这种情况下，有了这些样本作为基
础，对事情的推理预测的把握才能更大，对于事物的认知才能更加准确。这样，后续就能不
断靠推理来规避一些在这该领域下的陷阱，从而让自己能够跑得更快更稳。&lt;/p&gt;
&lt;p&gt;如果综合上面的论述，我可以发现，总是应该先去行动，因为推理没有行动的结果作为支
撑，是摇摇欲坠的。先行动而非先推理，确实是可以作为我在对于一些自己并不熟悉的领域
的一种行事的习惯，从而避免先入为主，然后想太多，最后什么都没做，白白错过了可能的
机遇。&lt;/p&gt;</description>
    </item>
    <item>
      <title>让树莓派 5 跑上“香草”主线内核：精简裁剪、交叉编译与部署全流程</title>
      <link>https://blog.bktus.com/archives/mv9qo5/</link>
      <pubDate>Sat, 14 Jun 2025 01:09:13 +0200</pubDate>
      <guid>https://blog.bktus.com/archives/mv9qo5/</guid>
      <description>&lt;h2 id=&#34;摘要&#34;&gt;摘要&lt;/h2&gt;
&lt;p&gt;本文系统记录了我如何将树莓派 5 打造成主线 Linux 内核（Vanilla Kernel）的极简开发
与测试平台——包括仓库极简裁剪思路、定制化内核配置、交叉编译与自动部署脚
本、overlay 移除技巧，以及长期与主线社区同步维护的实战心得。适合关注 Linux 主
线、ARM64 适配、内核开发、Upstream 贡献或喜欢折腾内核的极客们参考和实践。&lt;/p&gt;
&lt;h2 id=&#34;背景与动机&#34;&gt;背景与动机&lt;/h2&gt;
&lt;p&gt;最近一段时间，我在深入研究 Linux Kernel 的理论和架构，准备正式切入操作系统内核领
域。因此，特意购买了树莓派 5 作为开发板，用于学习和实践内核开发。然而刚上手就发
现，目前树莓派 5 并不能直接跑主线 Linux 内核，只能依赖&lt;a href=&#34;https://github.com/raspberrypi/linux&#34;&gt;树莓派团队维护的内核仓
库&lt;/a&gt;。当时最新的分支是 rpi-6.14.y（现在是
rpi-6.16.y），仓库的维护方式是“动态拉取上游主线代码+rebase+大量自定义补丁”，涉及
上万行的修改和历史反复变动。&lt;/p&gt;
&lt;p&gt;这些定制补丁对于官方内核在树莓派上稳定运行、兼容所有功能确实非常重要，但对我这种
&lt;strong&gt;纯粹想研究主线内核特性&lt;/strong&gt;、关注内核本身的开发者来说，这些补丁反而变成了负担：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主线同步困难，merge 经常出冲突，&lt;/li&gt;
&lt;li&gt;版本历史频繁重写，难以回溯和比较，&lt;/li&gt;
&lt;li&gt;验证主线新特性或做反馈变得不直观。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我对比了 x86 开发板，发现它们大多能直接运行主线内核，但价格昂贵，性价比远不如树
莓派 5。因此，我开始思考，如何让树莓派 5 也能顺畅运行主线内核，真正实现随时体验
和测试内核最新特性，并为 ARM64 平台反馈问题、贡献补丁提供便利。我的目标很明确：
用最少的补丁、最贴近 upstream 的方式，让树莓派 5 成为个人主线内核实验和学习的理
想 ARM64 平台。&lt;/p&gt;
&lt;h2 id=&#34;仓库结构与修改范围&#34;&gt;仓库结构与修改范围&lt;/h2&gt;
&lt;p&gt;我的做法十分简单却又直奔核心——只保留最必要的驱动与补丁，其余全部紧跟主线。仅对
drivers/ 目录做补丁，聚焦核心硬件支持，主要包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SD 卡驱动&lt;/strong&gt;：保证树莓派能正常引导，内核能加载根文件系统。虽然启动固件自带部
分初始化功能，但主线内核仍需驱动挂载根文件系统。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;有线网卡（Ethernet）&lt;/strong&gt;：方便通过 SSH 实现远程登录、下载新内核镜像、远程开发
和调试，是内核开发过程中最重要的 IO 通道之一。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;UART 串口&lt;/strong&gt;：作为内核调试和 early print 的输出窗口，可以直接观察内核日志，判
断启动和运行状态。&lt;/p&gt;</description>
    </item>
    <item>
      <title>友情链接</title>
      <link>https://blog.bktus.com/friends/</link>
      <pubDate>Sun, 08 Jun 2025 01:13:38 +0000</pubDate>
      <guid>https://blog.bktus.com/friends/</guid>
      <description>&lt;p&gt;这里汇集了我在网络世界中欣赏和推荐的优秀博客、网站与朋友们的作品。无论是技术干
货、生活随笔，还是创意分享，都在此与大家相互链接、相互支持。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://z.wiki/&#34;&gt;敖武的博客&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>搭建个人链式VPN网络：高效隐私保护、设备无限制管理与远程访问</title>
      <link>https://blog.bktus.com/archives/ozzkto/</link>
      <pubDate>Mon, 02 Jun 2025 19:20:00 +0200</pubDate>
      <guid>https://blog.bktus.com/archives/ozzkto/</guid>
      <description>&lt;p&gt;在某些场景中，我们可能需要搭建一个链式 VPN 结构，即先让内网设备连接到自建的
WireGuard 服务器（如个人 VPS），再通过该服务器将所有流量转发到另一个 VPN（公司、
学校或商业 VPN 服务）后才进入互联网。搭建这种「VPN 套 VPN」的网络架构，有以下明
显优势：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;强大的隐私保护：内网设备的数据流量首先通过自己搭建的 WireGuard 加密隧道传输至
个人 VPS，再由 VPS 二次通过商业或公司 VPN 进行转发，最终从该 VPN 的 IP 出口访
问互联网。这种方式彻底避免了使用 VPS 自身 IP 地址直接访问目标网络，大大降低了
个人 IP 被跟踪或泄露的风险。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;集中化便捷管理：所有客户端设备统一连接到单个 WireGuard 服务，免去逐一配置每台
设备的麻烦。更重要的是，它还能巧妙绕过一些商业 VPN 服务商设定的账号设备数量限
制，一次付费，所有设备共享。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;灵活便捷，轻松切换：由于商业或公司 VPN 配置仅在自建 WireGuard 服务器端修改一次
即可生效，下游客户端（手机、电脑等）无需单独调整。这使得更换或重新配置上游 VPN
时更加迅速和便捷，大大提高日常维护的效率。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;打造专属虚拟局域网，实现跨设备互通：一旦所有设备连接到自建的 WireGuard VPN 服
务器后，将自动获得统一的 VPN 虚拟局域网 IP 地址（例如：10.8.0.0/16）。处于该网
络中的设备能够直接互相通信，无需额外设置。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种便捷性意味着无论你身处何处，都能轻松实现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;远程 SSH 登录：随时访问家中或办公室的服务器。&lt;/li&gt;
&lt;li&gt;私有 NAS 媒体访问：在外轻松访问家中 NAS 存储的媒体文件。&lt;/li&gt;
&lt;li&gt;远程办公：随时随地安全访问公司内部网络资源。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;方案&#34;&gt;方案&lt;/h2&gt;
&lt;p&gt;经过本人的探索和实践，我逐步摸索出了自己的一套链式 VPN 方案。总体来看，我的方案
完全基于 Docker 部署，所用到的核心组件有：&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于对事物定性判断的一些体会</title>
      <link>https://blog.bktus.com/archives/di3xgp/</link>
      <pubDate>Thu, 06 Mar 2025 01:06:31 +0100</pubDate>
      <guid>https://blog.bktus.com/archives/di3xgp/</guid>
      <description>&lt;p&gt;在现在，生活中充斥着各种信息。我能够从各种消息来源获取各类信息，比如新闻、社交平
台、长短视频等等。在这些信息中，包含着对周遭世界的各种变化的概要情况，或者是细节
分析。其中不妨也有一些基于现在的情况，对一件事情进行定论和判断。有的分析往左边
说，有的分析往右边说，有的分析自称“中立”。总之，众说纷纭，莫衷一是。我也是很好
奇，我该如何判断这件事情的性质？哪一些是“对”的，哪一些是“错”的？&lt;/p&gt;
&lt;p&gt;很多时候，我发现人们对一件事情的判断，其实是处处受到其自身所处的状态的影响。自身
所处的状态又受到其社会地位、人际关系、经济实力、自身经历等影响。而且，对于一件事
情，若非当事人，旁观者从各种消息中得到的总是这个事件的某个描述，描述者也将会有意
无意在描述中渗入一些倾向性，这是不可避免的。比如说，虽然这个描述者说得都是事实，
但是对于事实的描述也可以有侧重。有些他觉得重要的或者有意义的细节，他会多说。而另
一些他认为不重要的，当然就会少说，甚至直接忽略。一件事情，除了其发生的时候的过程
以外，还涉及到各种背景，包括但不限于参与者各自的背景，还有事情发生之前的各种关联
性事件，甚至当事人在某一时刻闪过的想法。如果要在描述中，把这些事情都交代详尽，那
是不可能的，更不用说有些细节根本难以探知。&lt;/p&gt;
&lt;p&gt;很多时候我注意到，对于一件事情、一个事物或者一种现象，从两个完全不同的立场出发，
完全可以各自发展出一套非常有道理且充满正义的说法。然而从这两个不同的立场看对方，
往往会轻易给出非常尖锐的批评，双方都可以援引各种实际的例子。有趣的是，这些批评可
以互相套用，用在各自身上，从切换一下立场，然后按照这个立场的模式进行一套有逻辑的
推理，即可很好对号入座。所以，我尝试对我身边发生的事情、我感兴趣的大事、我忧虑的
事情和我日常的小事等等进行这样的正反分析，几乎都能得出两个相反的判断和结论。在这
段时间内，我陷入了一种分裂。我经常苦苦思索，到底哪一种说法是对的，按照事情的发
展，哪一种立场可以笑到最后。我也渴望，一种中立、理性、客观的立场。然而，每当我认
为某个人阐述的这种立场非常客观，非常中立，一段时间后就会有针对持有这种立场的人的
批评之声。要么就是，客观到味同嚼蜡，我都不想继续继续听下去。我为什么会这样，我常
常反思。&lt;/p&gt;
&lt;p&gt;在长达几年的断断续续地思考后，我最终得出我自己的结论，寻找一种”中立“且”客观“的立
场观点，或者是对一件事物去苦苦追寻”真相“都毫无意义。这样反而会让自己活得非常累。
根本的原因在于，我自己是有自己的立场的，不需要再去强迫自己接受其他人的立场。我的
立场来源于个人喜好、社会地位、经济实力、过往经历、经验见识等等，这些也是我上面所
提到的影响个人对于事物判断的几个影响点。所以，我会在某些时候，对于一些声音感觉
很”客观“，对于另一些声音觉得很反感。那是因为，其实对于这些事情早已经在自己的内心
产生的自己的判断。那为什么我不能去乐呵呵地接受所有的声音？我承认，我可以去听取所
有的声音，并思考其他的声音中包含的那些道理，然后尝试去加深自己对于一件事情的认
识，但其实很难做到去开心地接受。然后，让我去站在我自己的对立面去思考，完全可以，
但是对于我自己并无意义，因为我毕竟无法成为对立面的那一些人，很难按照他们的立场来
做或者享受这样的立场带来的利益。&lt;/p&gt;
&lt;p&gt;我更加倾向于认为，每个人都有自己的基本法，基本法是按照自己的个人情况量身定制，是
自己对于周遭世界该怎么样才会“完美”的朴素认识。我自己是立法者，为了对于一件事情进
行认识和判断，我可以通过基本法衍生出一些实际的法律。我自己也是法官，根据基本法衍
生出的现行法律，对一件事情进行定性和判断。我是否要去参考其他人的定性和判断，可
以，但是不是必须，应该更多地秉持着一种认识世界上的思想多样性的态度。别人如何判
断，那是基于其他人的基本法，他们的基本法可能与我有相似之处，也可能与我大相径庭，
完全相同的可能性非常小。那既然不是同一套基本法，那么各自也会衍生出自己的一套实际
的法律。既然他们与我所处的体系都不同，我为什么要完全接受一种立场？&lt;/p&gt;
&lt;p&gt;对待日常生活中，那些自称的”中立者“的态度，基于我自己的这套观点，也有了一些清晰的
方法应对。这些中立者，其中一类，无非是宣称自己所述的是事情的真相，但是前面已经说
过，一件事情的真相是很难原汁原味的还原的，各类描述都带有自己的侧重，而且总有不为
人知的细节未曾曝光。既然这样，那空谈真相还有何意义，即使事情有一个绝对的争相，那
理论上也只有神知道了。所以我觉得，我大可放下“追求真相”的精神洁癖，基于我自己所知
道的，去给出我自己的看法。还有一类，说自己的观点很“中立”和“客观”，这是可笑的，因
为他也是一个人，有自己的基本法，如何能抛却七情六欲，成为一个神仙，从而来达到“中
立”和“客观”。如果有，那就有一种相对的中立和客观，那就是穷尽世界上的所有的立场与
其对应的思想观点，以及他们对于这件事情的看法，然后全部精确记录并阐述。有些“中立
者”正在向着这方面努力，这类人，我觉得确实是往正确的方向在走。但是，我作为一个
人，听取这么多的立场有什么意义，难道我能随心所遇地切换自己的人生，来去实地体会和
践行这些思想观点和判断？类似地，就比如一个问题有即使多种解决的方法，但是最终我还
是会用一种方法去解决它，选择哪一种方法完全是个人的事情。所以在这里，我认为某个事
情该怎么判断，听从自己基于自己立场的判断即可，在自己的这个参考系下，这就是中立和
客观的了。其他的参考系下的看法，又与自己何干？当然，我们也可以多看看其他的参考
系，但这绝不能作为一个强制的要求。如果自己想真正独立，那么维护自己的参考系的独立
性，捍卫自己的是立场、观点和偏好，是非常重要的。&lt;/p&gt;
&lt;p&gt;我也注意到，对于基本法某些部分或者条文有比较多相似性的一些人，是完全可能聚合成一
个团体的。一个人独自战斗地久了，找到和自己有相似观点的人，还是一件很欣喜的事情
的。对于一些事情，一个人完全可以去发现和寻找自己的团体，不一定要加入和做些什么实
际的事情，也可以是一种内心的靠拢。很多时候，人们会为了一件事情的看法，相互攻讦，
给不同立场的人扣上一顶帽子。如果这个时候，一个人能够站在一个自己舒服的团体下，那
可以减轻很多压力并有可能产生一种安定感。很多情况下，我觉得“站队”是对个人有利的。
更多的人如果能通过“站队”，共同努力去维护和传播一种相似的立场，才能让一种“共同立
场”持续存在并产生力量去真正推动现实中的一些事情。这样才有可能，在大家去解决某个
社会性问题时去考虑这种立场，然后去采取这种立场提供的方法或者部分思路。如果真能这
样，个人才能够在这种情况下获得更多的利益，让自己觉得自己的观点偏好与自己所喜爱的
有了更多的意义。&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于我</title>
      <link>https://blog.bktus.com/about-me/</link>
      <pubDate>Sun, 17 Nov 2024 20:12:17 +0000</pubDate>
      <guid>https://blog.bktus.com/about-me/</guid>
      <description>&lt;p&gt;我叫 Saturneric ，任何时候都可以直接称呼我 Eric。目前坐标德国。&lt;/p&gt;
&lt;h2 id=&#34;概况&#34;&gt;概况&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;身份职业：
&lt;ul&gt;
&lt;li&gt;硕士生（KaIT, 信息学, 2025-）&lt;/li&gt;
&lt;li&gt;后台工程师（腾讯，2022-2024）&lt;/li&gt;
&lt;li&gt;开源软件贡献者（GpgFrontend及其他项目，2021-）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;技术领域：C/C++，GnuPG，Linux Kernel，Qt，Docker。&lt;/li&gt;
&lt;li&gt;操作系统：Debian，macOS，Windows，Android，iOS。&lt;/li&gt;
&lt;li&gt;常用软件：Firefox，Thunderbird，Matrix/Element，Joplin。&lt;/li&gt;
&lt;li&gt;兴趣爱好：天文（观测），历史（中国古代史）。&lt;/li&gt;
&lt;li&gt;掌握语言：汉语，英语，德语。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;常用链接&#34;&gt;常用链接&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;邮箱：&lt;a href=&#34;mailto:eric@bktus.com&#34;&gt;eric@bktus.com&lt;/a&gt;（优先使用）&lt;/li&gt;
&lt;li&gt;Matrix：&lt;a href=&#34;https://matrix.to/#/@eric:bktus.com&#34;&gt;@eric:bktus.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Git：&lt;a href=&#34;https://git.bktus.com&#34;&gt;https://git.bktus.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Github：&lt;a href=&#34;https://github.com/saturneric&#34;&gt;https://github.com/saturneric&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;联系我&#34;&gt;联系我&lt;/h2&gt;
&lt;p&gt;如果你想与我建立联系，请参考&lt;a href=&#34;https://blog.bktus.com/contact-and-verification/&#34;&gt;联系与验证&lt;/a&gt;中的说明。&lt;/p&gt;
&lt;h2 id=&#34;站点声明&#34;&gt;站点声明&lt;/h2&gt;
&lt;p&gt;关于本站的相关法律和隐私申明,请参考&lt;a href=&#34;https://blog.bktus.com/site-declaration/&#34;&gt;站点申明&lt;/a&gt;中的内容。&lt;/p&gt;</description>
    </item>
    <item>
      <title>随笔</title>
      <link>https://blog.bktus.com/memos/</link>
      <pubDate>Sun, 17 Nov 2024 20:12:17 +0000</pubDate>
      <guid>https://blog.bktus.com/memos/</guid>
      <description>&lt;p&gt;这里记录着长文之外的灵感碎片、日常废话与即时状态。不定期更新，随看随走。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年四月第一周技术周报</title>
      <link>https://blog.bktus.com/archives/5mqhyo/</link>
      <pubDate>Sun, 17 Nov 2024 01:23:16 +0100</pubDate>
      <guid>https://blog.bktus.com/archives/5mqhyo/</guid>
      <description>&lt;p&gt;看了一下当时的周报，值得说的事情也就是关于日志整理的事情，然后就是关于一个配置下
发服务的多地部署。关于多地部署的事情，下一篇技术周报再详细说明。&lt;/p&gt;
&lt;p&gt;首先来说说，日志方面的事情。现在的话，线上有很多服务。然后目前 DEBUG 的日志，是
用了腾讯云的 CLS。而目前存在一些问题，这些服务的日志有些分散，不太好找。如果一个
请求跨越了多个服务，有可能需要研发去跨越几个日志集然后来定位问题。然后就是，这些
服务技术栈并不统一，并没有一个统一的日志监控框架来监控这些服务的状态。目前追踪跨
服务的请求使用 TraceID，TraceID 是在请求进入网关服务或者入口服务的时候自动生成
的。TraceID 有可能是纯数字，也有可能是数字带字母。后续的服务之间的请求基本上会带
有 TraceID 这个字段，用于追踪请求。然而，也还有很多请求内容里不带 TraceID，导致
服务没办法从请求本身来拿到 TraceID，只能索性重新生成一个，所以这些请求在各个服务
之间的 TraceID 都会不同。总而言之，理论上，正常情况下，一个 TraceID 将伴随一个请
求，从进入追踪范围到出追踪范围为止。&lt;/p&gt;
&lt;p&gt;另外还有个问题，就是这些个日志集中，日志内带有的字段也不太统一，有写日志集的请求
内容的字段叫 X，有些又叫 Y。有些字段日志的结构上有，实际输出的日志中却没有填写。
如此这些，都增加了新的研发上手定位 BUG 原因的学习成本。上述这些问题，都很让人头
疼。&lt;/p&gt;
&lt;p&gt;还有一个就是降本增效的问题，在目前的已有日志的基础上需要看看还有哪些日志可以精简
优化的。整个部门，每个月的单单存储和整理日志成本都十多万。而我负责的这一块的业务
量又占大头，日志量也是非常大的，每天大概有 540 亿条日志。所以，我需要在这一块多
下功夫。&lt;/p&gt;
&lt;p&gt;对于当前的的 TraceID 问题，我采取先把同样技术栈服务的 TraceID 的生成方式和传递方
式都改为统一的。对于 Java 技术栈的服务，用的无非都是 Spring Boot 框架。所以我对
每个服务都增加了一个统一的拦截器，来拦截请求和响应。对于请求，这些 Java 服务处理
的都是文本类型的请求，基本上都是 JSON 格式编码的。所以，无外乎就是检查 JSON 字段
中是否有相应的 traceId 字段，如果有的话，那就拿来用。具体就是把 TraceID 放置到线
程私有化存储中（MDC），伴随着这个线程处理。这个方法也有局限性，有些请求会在某些
步骤上进行异步处理，转移到其他线程池的线程上处理了。这样，TraceID 的追踪就丢失
了。我的办法是写一个包装类，接管所有异步处理的需求，参数与调用方式和原来一模一
样，然后在其中检查上一个线程中是否含有 TraceID 字段，然后把 TraceID 字段先放到包
装类产生的对象中。切换到另一个线程后，这个线程先看看包装类对象中是否有上一个线程
存下的 TraceID，如果有就提取这个 TraceID 然后记录到自己的私有化存储中。这样
TraceID 的追踪就不会中断了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年三月第四周技术周报</title>
      <link>https://blog.bktus.com/archives/0b0nkf/</link>
      <pubDate>Mon, 15 Apr 2024 22:04:06 +0200</pubDate>
      <guid>https://blog.bktus.com/archives/0b0nkf/</guid>
      <description>&lt;p&gt;本周有个插入的事项，就是说我们目前在使用某云服务商的 API，对于其中的 API 鉴权，
那边有更安全的方案。原先，我们应用调取云产品的功能时，是通过一个 AccessKey 和
AccessSecret 来的。在调用的时候，需要在 SDK 中提供这两个值，然后就可以在应用中使
用 SDK 提供的云产品 API 了。原先的安全要求是不能在代码中存储这两个值，公司会有某
种自动扫描机制，通过这个机制可以检测代码仓库中的敏感信息，这两个鉴权用的字段也当
然囊括在内。所以，我们一般都会把这两个值写在配置文件中，安全性会更好一些，也方便
更改。&lt;/p&gt;
&lt;p&gt;而现在他们说这两个值是静态的，无法在泄露的情况下快速进行更换。毕竟我们服务一般都
有几十上百个容器，而目前来说，启动配置虽然已经集中于各种配置中心里了，但是在技术
上是无法实现秒级别的动态更改的，必须在修改配置后重新启动容器。而容器的启动是无法
通过一次性重启所有容器来完成，必须进行分批重启以保证服务的平稳，没有十几分钟甚至
几十分钟是搞不定的。&lt;/p&gt;
&lt;p&gt;所以云提供商的技术团队提出了一个新的方案，通过向我们提供一些必要的而且泄露后不容
易造成直接影响的凭据（好像是一个密钥文件），然后通过在线认证的机制下发动态的验证
信息。这个过程比我上文提到的验证机制复杂许多，特别是我们需要在容器中纳入这样一个
配置文件，或者直接在 JAR 包中纳入。然后我们需要引入一个 SDK，来专门做这个动态验
证信息的获取，然后将这个信息通过某种方式传递给云产品的 SDK，最后才能实现云产品
API 的调用。&lt;/p&gt;
&lt;p&gt;这个具体的过程并不是我来跟进，我把这些问题交给其他同事了，由他们来具体执行。我只
是作为云账号权限的控制者，为他们提供密钥文件并给他们提供正确的方向即可。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年三月第三周技术周报</title>
      <link>https://blog.bktus.com/archives/ge5n6u/</link>
      <pubDate>Mon, 15 Apr 2024 21:47:09 +0200</pubDate>
      <guid>https://blog.bktus.com/archives/ge5n6u/</guid>
      <description>&lt;p&gt;本周值得注意的事项就是，测试人员那边反馈在测试环境下，某些账号突然无法正常使用的
问题。目前整个账号的体系还是在沿用老的系统。而在当前老系统中，账号信息使用某种特
殊的数据存储分成多个模块存储，每个模块相当于一张表。每张表都各有侧重，有些侧重于
与其他账号之间的关联关系，有些侧重于查询等等。这些账号无法使用的问题在于，其中最
重要的一张表也就是主表，这个用户的记录消失了。在其他表中该用户的相关记录还是存在
的。&lt;/p&gt;
&lt;p&gt;这就引发了我的各种猜想，是否是测试人员测试的过程中的环境弄混了？或者是某个服务的
配置有问题导致了部分应该写在测试环境的数据写到了生产环境去了？说代码写得有问题导
致了某些极端情况下，用户的主表信息写入失败？通过调查发现，最终要的查询表中，数据
结构还是完整的，而且能够反推出用户注册时候的微信账号。查询表只有在账号创建的时候
才会去写，后续基本不会再修改了。而主表中的数据应该是和查询表在用户注册的时候一块
写入。&lt;/p&gt;
&lt;p&gt;对于这个问题，后续推断应该是数据模块发生了某种问题导致数据丢失。而在我咨询数据模
块相关维护人员的时候，我还没说清楚问题，他们就说是测试环境并不保证服务的可用性，
可能发生任何问题。那么这个问题可能就无解了，因为如果是数据模块这层问题，我作为使
用方基本没有任何能力来自己解决。除非我能替换掉这个数据模块，使用更加稳定可靠的解
决方案。那对于这个问题，我只能够然同事手动清理查询表中的索引关系，然后在让用户重
新进入应用。当用户重新进入应用的时候，由于没有索引就相当于没有这个用户，此时就会
重新创建用户。后续几个月遇到了十几例相同的问题，没有办法，让同事添加了一段自动处
理这个问题的业务代码，以免去每次手动处理的麻烦。&lt;/p&gt;
&lt;p&gt;这个问题第一次出现将近一年后，由于某个重要客户反馈了这个问题。而又正好这个重要客
户当时半个月之内反馈的我们的各种问题有点多，领导对此十分困扰，所以对于我这个问题
他特别重视。领导后续找到我让我推动解决这件事，我同意执行，因为我也想知道问题具体
是什么。现在能够确定的是，问题出现在数据存储层，而这一层又不是我们直接控制，我们
只是使用这样一个产品。这个产品已经很老了，维护人员很少了，而且还有其他事情。他们
不愿意来主动寻找问题，也是情有可原的。所以想要推动他们的维护人员来解决，就只能抓
住具体且直接的证据来证明他们的问题在哪里。&lt;/p&gt;
&lt;p&gt;我以当时的了解，知道数据层分为缓存和落盘数据库，而且经过一年在各种问题的解决过程
中学习，我也能很熟练调取分析落盘数据库里的数据了。我调取了落盘数据库中的用户 ID
的倒序情况，发现从某个用户 ID 开始，后面就没有了。最近一年，用户报问题的用户 ID
以及新注册的用户 ID 是远远大于这个 ID 的。我又去日志中获取了一个最新注册的用户
ID，查询数据层，发现是有的。说明缓存中是有正常数据的，但是由于某种原因数据并没有
落到数据库中，而是在缓存满后直接消失了。&lt;/p&gt;
&lt;p&gt;这已经能够说明问题了。于是我将这些调查记录截图发给数据层产品的维护人员，并提了一
个工单，推动他们来解决这个问题。该问题的脉络我已经提前分析地很清楚明了了，而且又
有直接的证据，他们也开始认真对待这个问题。后面确实，他们重启某个模块后，这个问题
就好了。而且最终他们承认问题与缓存层落库的机制有关系。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年三月第二周技术周报</title>
      <link>https://blog.bktus.com/archives/88phw6/</link>
      <pubDate>Sun, 14 Apr 2024 20:33:44 +0200</pubDate>
      <guid>https://blog.bktus.com/archives/88phw6/</guid>
      <description>&lt;p&gt;本周相关的一些事项，我认为最值得讲得就是某个数据库接入层服务的给每一条数据加上键
过期时间。这个数据库接入层是一个 Java 服务，本质上做的工作就是将 Redis 与数据库
结合起来。对上的接口遵循某一个公司内部的特定协议，而对下则使用开源且很多人使用的
Java 包来访问 Redis 或者数据库。访问 Redis 使用的是 lettuce，而访问数据库用的就
是 mybatis。原来访问 Redis 其实用的是 Jedis，后面之所以改用 lettuce，是因为它在
高并发下的性能/资源表现更好一些。我认为具体地主要体现在多路复用连接，使得不需要
在连接池中维护很多连接，总之就是在连接上的开销不会很大。&lt;/p&gt;
&lt;p&gt;然后对于数据库来说，并非直接写入，而是在消息队列中写入一条插入指令并附上一些上下
文。这样消息中包含了写入数据库需要的所有信息了。然后这条消息队列也是自己在消费，
消费的时候将数据写入数据库，如果成功就 ACK 消息，失败了就让这条消息 5 分钟后再回
来。&lt;/p&gt;
&lt;p&gt;这个服务总的读写策略就是，如果一条数据查询来了，Redis 中没有数据时就将数据库中的
数据拉到 Redis。然后返回 Redis 中的数据。Redis 中有数据则直接返回。对于写入数据
来说，这条数据会双写 Redis 和数据库。修改数据的时候，操作复杂得多。因为这个
Redis 中数据是使用 HSET 的方式进行存储的，然后一条修改指令可能只是修改 HSET 中的
一部分字段。这个就需要对一些具体的情况进行讨论了，数据库指令也是根据具体情况来构
造。&lt;/p&gt;
&lt;p&gt;值得一提的事写数据库的时候，目前看前人升级了策略，不直接拿消息中的数据来写，而是
消费到消息时，直接从 Redis 中读数据（这个时候 Redis 是早就被双写了的），然后直接
将 Redis 中读区到的数据写入数据库。我认为这样做的好处是，让数据库中的信息尽快更
新。因为从消息投递到消息队列再到消费的过程中，这一条数据可能已经修改了好几次了。&lt;/p&gt;
&lt;p&gt;在这几周我发现这个服务在 Redis 中的缓存并未设置过期时间，而是依赖 Redis 实例中设
置的统一过期策略来进行数据淘汰。这个策略是在 Redis 数据存满的时候才会执行的，这
就会引入一个风险。根据我们云上分布式 Redis 的设计，如果 Redis 存储一直都是满的然
后这个时候有大量的数据写入操作（某种特殊的业务高峰期），这样云上分布式 Redis 为
了一次性腾出足够的空间会集中进行淘汰操作。这个时候无法处理任何请求，这种情况将持
续几分钟。这对于业务来说，存在较大影响，因为这个时候上游业务服务将无法读或者写入
数据了。而现实情况就是，这个服务的 Redis 一直处于满的状态。&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于个人对AWS服务的使用感受</title>
      <link>https://blog.bktus.com/archives/fms9jf/</link>
      <pubDate>Fri, 24 Nov 2023 21:07:50 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/fms9jf/</guid>
      <description>&lt;p&gt;&lt;strong&gt;原文经过 AI 润色，非本人文风。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;从 2022 年 11 月开始，我开始使用 AWS 服务，已经接近 1 年的时间了，而且不是免费套
餐。从一开始对它的使用感到新奇和陌生，到现在对它的了解更加深入，期间经历了很多有
趣的事情。那么，为什么我选择使用 AWS 呢？因为我个人有一些需要在 AWS 上运行的服
务，比如博客网站（Wordpress）、Git 仓库、RSS 订阅等等。当时，我觉得 AWS 在云服务
市场占有最大的份额，所以它的解决方案应该已经非常成熟了。对于 AWS，我还是有一定的
信任，愿意花钱购买适合的服务，以确保我的个人托管业务能够长期稳定运行。&lt;/p&gt;
&lt;p&gt;在开始使用 AWS 之前，我也尝试过免费套餐，但是一直没有找到合适的需求场景，所以用
了一段时间后就不再使用了。这样，我的免费套餐周期就白白浪费了。&lt;/p&gt;
&lt;p&gt;当我第一次接触 AWS 的时候，我首先尝试了 EC2 产品，并试用了 1 核心 1G 内存的
T2.micro 实例，但后来发现内存不够用，导致机器卡死。因此，我决定换成 T2.small 型
机器，它拥有 1 核心 2G 内存，并且我还增加了 SWAP 分区，每个月大概需要花费 17 美
元。虽然这个价格包括了带宽费用，但我仍然觉得有些贵。然后，我开始考虑是否可以使用
AWS 的保留实例，听说可以减少 60%-70%的费用，看起来非常划算。于是，我下定决心购买
了三年的保留实例，先支付了 170 美元，然后每个月承诺支付 4.75 美元。这样一来，每
个月的费用大约是 8.84 美元，这个价格看起来相对合理。&lt;/p&gt;
&lt;p&gt;然后遇到了一个坑，当时我配置了 30G 的系统盘和 10G 的数据盘，以为 30G 的系统盘是
免费的。然而，我又考虑到数据的安全性，因此还增加了定期快照备份，以为快照的费用不
会很多。最后，月度账单一出来，竟然要 20 美元！我很惊讶钱都花在哪里了？&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于主流道路的一些思考</title>
      <link>https://blog.bktus.com/archives/pzovx4/</link>
      <pubDate>Tue, 21 Nov 2023 13:33:24 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/pzovx4/</guid>
      <description>&lt;p&gt;一般而言，我们总是倾向于捡着他人走过的路来走。一旦偏离这个所谓的“大众路线”，我们
很可能就会觉得自己处于悬空状态，从而陷入一种循环地自我怀疑中，总认为自己处于一种
脚不着地的危险的状态。我感觉这是我们倾向于认为，大众的某种“主流”的观念是一种无可
辩驳地正确，从而不会去思考其中正确性来源的几方观念的出发点，以及这些观念背后的逻
辑。&lt;/p&gt;
&lt;p&gt;具体来说在我们的生活中，常常会有一种压力，让我们按照主流的方式去行动。这种压力直
接来自社会与文化的期望、他人的看法以及我们自身对所谓“成功”的刻板印象。我们害怕偏
离主流，也害怕在便利主流后失败，从而被周围的人认为是典型异类或失败者的活生生的例
子。因此，我们倾向于随着周围的人选择安全、确定的道路，即那些大家已经验证过的方
法。顺从主流方式可以当然可以带来一些实实在在的成果，但这种方式并不一定最适合作为
单独个体的某个人，你可能并未从自身的具体情况的细节出发来选择，而可能带有一定的盲
目性。我们不断仰视其他人的成功，给自己制造一个个“神像”，时时刻刻去回忆去参拜，在
谈论中夹杂这感叹、羡慕或者是丝丝的嫉妒。但我们强调要像这些“神像”看齐，要成为他
们，但却始终忽视了自己的特点。我能不能成为另一种定义下的“神像”？这个是很多人都很
少去思考的问题，很多时候大多是人可能认为这种思考无意义。&lt;/p&gt;
&lt;p&gt;这个时候想象一下，如果别人向你寻求有关他们当下困难的决定或者说是某段时期的人生道
路，你可能会毫无思考地说出这些“主流”方式，但当别人进一步问你为什么这些方式是正确
的？是否可以列出实际的步骤并从自身出发去论证这些步骤的合理性？你可能第一时间就不
知道如何回答了。&lt;/p&gt;
&lt;p&gt;虽然说，当你跳出固有的“大众”思维去思考的时候，想着我可否在这个主干道的这个岔路口
上走拐进另一条路。这可能会产生很多困惑，因为这对于你思维的惯性来说，何尝不是一次
急刹车？也许你第一次考虑一种未曾设想的可能性。并且有可能突然发现原来这件事的逻辑
是非常复杂的并陷入一种思维错乱中。在你尝试你认为是正确的新方法时，也有可能发现你
其实是走了弯路。最后你可能会得出结论，主流方法也是有一定道理的，是基本上正确的。
然而，只有意识到这些，有意识地去了解这些，在拥有可行性的基础上去试着尝试这些，你
才能在不断尝试和试错中更清晰地把握事情的本质，最终正确认识“主流”方式的合理性以及
它为什么会存在。这个时候你的脚或许真正开始走在实地上，这大概会逐渐在内心深处建立
处一种内在的自信，不断引导你尝试其他的可能性，从而有可能找到最适合你个人特质和当
下实际情况的道路。&lt;/p&gt;
&lt;p&gt;所以，我个人认为不要因为害怕事情的复杂性而放弃寻找其他解决方法的可能性。这个时候
要相信自己的现有的能力和基于大量有效思考而对事物判断产生的直觉，不要过分依赖他人
的意见和观点，从而自己的一套思想理论和解决问题的宏观的体系。最重要的是，要始终坚
持自己的价值观和目标，顺着这个内心的最终指引找到真正适合道路，才能有效避免在大量
的思考和尝试汇总迷失方向。&lt;/p&gt;</description>
    </item>
    <item>
      <title>自建图床服务并配置免费CDN全球加速 过程记录</title>
      <link>https://blog.bktus.com/archives/57cscu/</link>
      <pubDate>Sat, 18 Nov 2023 15:34:11 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/57cscu/</guid>
      <description>&lt;p&gt;个人有一些图片托管的需求，在很多场景下比如说在博客文章中插入图片，在社交网站上分
享图片，抑或是个人开源项目中的图片等等，都需要在文档（特别是 MarkDown）中嵌入一
个 URL 直链来指向图片。对于一些免费的图床服务商，个人感觉并不是很信任。数据安全
是一方面，另一方面如果服务商跑路了，那么很多原先我创建的链接都会失效。据我所知，
这样的例子比比皆是。&lt;/p&gt;
&lt;p&gt;网上还有一些教程将 GitHub 当成免费图床来用。这样做弊端也很明显，GitHub 在国内的
访问速度非常慢，图片加载很慢。另外，缺少很多图床该有的功能，比如说自动压缩，自动
转换成 Webp，自动重命名等等。这样做也是不太可行的。下面就是一个我将 GitHub 用作
图床的例子。每次我还需要将图片移动到代码仓库里，然后 commit，push，我个人感觉很
麻烦。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Image&#34; loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/1afe06e2-82d2-fa2c-d2e8-17ac420b42c2-2.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;还有一段时间我试过把 WordPress 的 Midea 库当作图床来使用，但是我发现图片链接中带
有 wp-content/upload 这样的路径。然后链接中还会出现图片的名称。我感觉并不是很雅
观，而且在隐私的保护中有一种说不好的感觉。就像是别人一看这个 URL 链接，就能获知
一些图片以外的信息。下面就是用 WordPress 的 Media 库当图床例子。可以看到，产生的
直链不是很美观，而且还能暴露一些信息。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/4048195f-be6c-2764-6418-bef3891ca4cb-2.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;所以，我这边产生了自建图床服务的想法。这种图床最好能自动转换 jpg、png 格式的图片
为 webp。这样图片就能比较高质量、快速地在用户浏览器中加载出来。有关 WebP 的简要
介绍如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;WebP&lt;/strong&gt; is a &lt;a href=&#34;https://en.wikipedia.org/wiki/Raster_graphics&#34;&gt;raster
graphics&lt;/a&gt; &lt;a href=&#34;https://en.wikipedia.org/wiki/Image_file_format&#34;&gt;file
format&lt;/a&gt; developed
by &lt;a href=&#34;https://en.wikipedia.org/wiki/Google&#34;&gt;Google&lt;/a&gt; intended as a replacement
for &lt;a href=&#34;https://en.wikipedia.org/wiki/JPEG&#34;&gt;JPEG&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Portable_Network_Graphics&#34;&gt;PNG&lt;/a&gt;,
and &lt;a href=&#34;https://en.wikipedia.org/wiki/GIF&#34;&gt;GIF&lt;/a&gt; file formats. It supports
both &lt;a href=&#34;https://en.wikipedia.org/wiki/Lossy_compression&#34;&gt;lossy&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/Lossless_compression&#34;&gt;lossless&lt;/a&gt; compression,&lt;a href=&#34;https://en.wikipedia.org/wiki/WebP#cite_note-8&#34;&gt;[8]&lt;/a&gt; as
well
as &lt;a href=&#34;https://en.wikipedia.org/wiki/Computer_animation&#34;&gt;animation&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/Alpha_compositing&#34;&gt;alpha
transparency&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年三月第一周周报</title>
      <link>https://blog.bktus.com/archives/onjhri/</link>
      <pubDate>Wed, 15 Nov 2023 21:33:01 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/onjhri/</guid>
      <description>&lt;p&gt;最近，合规的要求逐渐渗透到技术层面。最近的一段时间，总有产品来找，说要实现这样那
样的合规需求。或者是，做一些什么合规的调查问卷。我感觉，合规也主要就是说对于用户
信息的存储、访问需要规范化，然后用户能够逐渐开始掌控自己的数据。然后还有一些人事
上、组织架构上的变动对于技术层面造成的冲击，比如说一个业务被调度到其他部门去了，
然后我们还在一直和这个业务共享数据库等资源。这个时候费用问题就突出了，就是说钱该
算在那边。虽然是一个公司、一个事业群，但感觉可能是由于公司内部的核算机制问题，对
于这些成本问题还是比较较真的，总会掰扯什么：他们用了我们的数据库，钱还在我们这边
什么的。有时候感觉，这些都是属于内部消耗，并不是出于发展的眼光看待问题。另外，别
的业务可能由于什么需求调整，需要修改一些公用的数据库结构或者接口，就比较麻烦了。
因为这个时候，我们为他们花费工时来做这些事情，并不能得到任何肯定。但是，又会被那
边的人催着，天天轰炸。自己夹在中间，感觉就比较难受。&lt;/p&gt;
&lt;p&gt;然后，我&lt;a href=&#34;https://blog.bktus.com/archives/3680&#34;&gt;上个周报&lt;/a&gt;提到的 PHP 网关迁移的问
题，其实前一两个月就开始在做了。其实也早就写好了，但是在后续切换流量到新服务的时
候，总是会遇到这样那样的问题。具体表现就是，测试环境流量切换很久了没有人来找，一
切正式环境这样那样的人就来找了。所这个接口突然用不了，那个接口突然报错什么的。这
种情况下，由于问题发生在线上，只能先把流量切回去再分析问题。一来二回，一个星期就
过去了。有时候，切换了 4、5 天才会有人来找。这样一个流程下来久更久了。&lt;/p&gt;
&lt;p&gt;leader 一直说这件事情做了很久如何，但实际的情况就是这样。虽然这个服务的后续具体
的代码编写和维护工作并非我来做了，但是我也知道一个新的服务要能够完全替代就有的服
务必须有一个这样的流程。因为在缺乏文档和测试用例的情况下，你不知道一个接口有什么
暗藏的机制，也无法完全清楚我写的代码是否和原来的等效。所以执行层面，很多事情没有
明确汇报，但是我感觉管理上也要能体会到。虽然过程比较反复、艰难，但最终这个服务的
重构工作在本周还是完成了，所有的流量都迁移到新的服务上了。也就是代表，这个老 PHP
网关的生命周期终结了。 我接手主要的后台业务也快半年了，现在发现刚接手的时候由于
缺乏经验，总感觉别人的技术高深莫测。但是，自己接触久了才知道里面有这样那样不完善
的地方。还存在一些设计缺陷，非常严重的缺陷都有。比如说把 Redis 当作数据库使用，
说白了就是没有设置缓存过期时间，然后 Redis 里面的数据又很重要不能丢失。这对服务
里面还存在着一些缺乏文档、维护人员早已离职的老旧服务，这些老旧服务基本上平时无法
来仔细研究。但这些服务中总有那么一两个依然在被访问，或者早就不能访问了，客户这几
天突然发现然后急着催我们解决。很多安全问题也需要整改，某几个 API 账号有一些高位
的权限需要收敛，但是我并不知道这个几个账号具体是做什么的。这些问题，就是日常频繁
遇到的，很难避免。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年二月第四周技术周报</title>
      <link>https://blog.bktus.com/archives/rr0u6h/</link>
      <pubDate>Wed, 15 Nov 2023 20:25:05 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/rr0u6h/</guid>
      <description>&lt;p&gt;本周我发现有些服务框架写得并不是很好，特别是某些 Java 框架。当 CPU 占用达到 40%
左右的时候，就会出现大量的超时现象。这些服务，CPU 核心和内存容量不是不多，工作线
程数目也不是不够。但是，就是跑不满 CPU。用 Java 性能工具分析发现，其实发现大部分
工作线程处于 Idel 或者 Waiting 状态。目前综合所有情况分析，还是百思不得其解。NIO
也用上了，还用的是 Netty 框架，但是吞吐量就是上不去。通过对于线程的分析，发现并
没有特别繁忙的业务线程。推断应该是 IO 或者某种等待机制导致了这种低处理效率。 这
次我是准备通过削减节点数量来降本，在执行前并没有考虑特别多的因素。所以我在削减节
点容量的时候，只是通过查看 CPU 的负载来判断节点是否能够承受。当我将北京地域的
workload 平均 CPU 占用率提升到 35%-40%的时候，整个服务出现了大量的超时现象。当时
把我吓了一跳。后面从监控上分析，几乎是整个背景地域的节点都超时了，也就是处于一
种”休克“状态。&lt;/p&gt;
&lt;p&gt;本周也继续重构某一个老的 PHP 网关服务，新的网关用 Java 写成。但是我其实不是很赞
成网关用 Java，毕竟 Java 这种语言的执行特性很大程度上决定了它不适合特别高的并
发。并且，我们目前所用的都是 JDK 8，并没有引入轻量级的线程，每个 4c8g 容器内线程
最多也就 800 个，多了线程切换开销就会特别大。所以单个容器的吞吐量有限，承载同样
的流量需要更多的容器。刚开始我是用 Go 重写的，这个框架很不错而且也有专门的团队维
护，但是 leader 还是让我用部门自研的那个 Java 框架。可能人事上的考虑居多吧，无
奈，我还是先写吧。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年二月第三周技术周报</title>
      <link>https://blog.bktus.com/archives/o6wu6l/</link>
      <pubDate>Wed, 21 Jun 2023 19:54:06 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/o6wu6l/</guid>
      <description>&lt;p&gt;本周主要处理一个节前发现的风险项。某个服务，在使用 Redis 的时候并没有为键设置
TTL，而是寄希望于 redis 的淘汰策略。我看这个服务使用的 Redis 设置了 LRU 淘汰策
略。这种策略看似比较完美，但是当某一较短时间段内，写入流量很大的时候，存在隐患。
这个时候 Redis 会触发淘汰过程，并集中尽力于此，以求能腾出足够的空间。这意味
着，Redis 不能很好地执行查询等正常操作了。这会造成业务层对 Redis 的读写延时均出
现剧烈波动。到现在，我已经遇到过 2 次这样的问题了。而且不设置 TTL，Redis 一直处
于 100%的使用率状态，我们从容量上并不能获知按照现在的业务量配置多少购买容量足
够。业务低峰时期是否能够通过缩容降低成本也是不能确定的。所以，为 Redis 留出一个
足够的可用空间是十分重要的。&lt;/p&gt;
&lt;p&gt;所以，我需要改造这个服务，使之对每个写入的新键设置 TTL。按照 Redis 的逻辑，如果
键在写入的时候已经存在，则也会被设置一个 TTL。为了业务稳定，我不求所有的键都设置
TTL。所以舍弃了在遍历 Redis 寻找未设置 TTL 的键的方案。其实我调研过这个方案，在
遍历的时候，使用需要游标来做。设置的 TTL 长短也有讲究，为了防止同一时间大量键过
期造成延时的大波动，设置 TTL 的时候在基础时长后加入了随机时长。假设基础时长为
T，那么加入随机时长后，TTL 的长度会处于 T ～ 2T 之间。这意味着，要求存留时间越长
的键，过期的分布也越广。这能够确保业务延时更加平稳，防止数据库压力过大。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年二月第二周技术周报</title>
      <link>https://blog.bktus.com/archives/q1pqco/</link>
      <pubDate>Wed, 21 Jun 2023 19:37:29 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/q1pqco/</guid>
      <description>&lt;p&gt;从一月底到二月初，都属于春节的范畴。期间，负责保障春节阶段的运行，需要随时待命处
理线上问题。我一直处于一种担忧的状态，好在线上问题并没有主动找上门。整个春节期间
维持整体不动是最好的。 这周我在评估一个重要的需求，所带来的影响。我认为，对于一
个新的业务需求，特别是应用于一个复杂的业务系统，需要考虑多方面的影响。如果这个时
候，对这个系统并不是特别熟悉，经验不多的话，最好选择做最小改动。这不是保守，而是
将影响控制在你可以想象地到的地方。因为你不会知道在什么地方，某个违背直觉的机制在
运行重要的业务逻辑。得出这样的结论，并不是出于我的想象。&lt;/p&gt;
&lt;p&gt;这篇文章写于半年后，到我写这篇文章的时候，我已经遇到至少两次这样的事情了。当时我
对某个服务做出了大刀阔斧的调整，在调整完的时候，一切正常。发布后，也看似正常。直
到若干星期之后，我偶然发现了某个串联上下游的机制，它差点受到我的影响。在承接一个
业务系统的时候，很大概率它是转接和很多手的，藏有很多你不知道的历史，所以框架、核
心逻辑能不动就不动。 然后，本周彻底解决了针对一个安全加密服务加密接口不兼容中文
的问题。主要的问题是，它将加密的原文直接作为 Redis 的 Key。当原文中存在中文，会
发现虽然 Key 存储了，但是找不到。我的方案是在存储的时候，Key 的内容不要直接包含
任何业务原文，先取哈希。这样既能够避免一些编码、兼容的问题，也可以大大提升安全
性。&lt;/p&gt;</description>
    </item>
    <item>
      <title>理解 Kubernetes 中的 CPU 资源分配机制</title>
      <link>https://blog.bktus.com/archives/fhs17u/</link>
      <pubDate>Tue, 20 Jun 2023 23:26:27 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/fhs17u/</guid>
      <description>&lt;p&gt;Kubernetes（k8s）是一种流行的容器编排平台，它允许开发人员在云环境中部署、管理和
自动化容器化应用程序。在 Kubernetes 中，CPU 资源的分配是一个关键的问题，它直接影
响着应用程序的性能和可靠性。本文将介绍 Kubernetes 中的 CPU 资源分配机制，包括
CPU 请求和限制、CPU Share 机制以及 CPU 调度器等相关概念，以帮助开发人员更好地控
制容器的 CPU 分配，从而提高应用程序的性能和可靠性。&lt;/p&gt;
&lt;h2 id=&#34;cpu-分配单位&#34;&gt;CPU 分配单位&lt;/h2&gt;
&lt;p&gt;在 Kubernetes 中，CPU 的分配单位是 millicpu（毫核），一个 CPU 资源等于 1000 毫
核。例如，一个 Pod 请求 0.5 个 CPU 资源，可以表示为 500 毫核。它是基于 Linux 内
核的 CPU 分配机制实现的。在 Linux 内核中，CPU 时间是以时间片的形式分配的，每个时
间片通常为几毫秒。Kubernetes 利用这个特性，将 CPU 时间片分配单位转换为毫核。&lt;/p&gt;
&lt;h2 id=&#34;cpu-资源分配机制&#34;&gt;CPU 资源分配机制&lt;/h2&gt;
&lt;p&gt;在 Kubernetes 中，CPU 资源的分配是通过两种方式来实现的：CPU 请求和限制。CPU 请求
用于告诉 Kubernetes 调度器，该 Pod 至少需要多少 CPU 资源才能正常运行；CPU 限制用
于告诉 Kubernetes，该 Pod 最多可以使用多少 CPU 资源。如果节点上可用的 CPU 资源不
足以满足 Pod 的 CPU 请求，该 Pod 就无法调度到该节点上运行。如果节点上可用的 CPU
资源不足以满足 Pod 的 CPU 限制，该 Pod 仍然可以运行，但可能会受到 CPU 资源的限
制，导致运行缓慢或者出现其他问题。 需要注意的是，CPU 请求和限制是 Kubernetes 中
的两个独立的概念。通常情况下，应该根据应用程序的实际需求来设置 CPU 请求和限制。
如果设置的 CPU 请求过低，可能会导致 Pod 无法正常运行或者运行缓慢；如果设置的 CPU
限制过高，可能会导致节点上的其他 Pod 的 CPU 资源不足，影响整个集群的性能和可用
性。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年一月第二周技术周报</title>
      <link>https://blog.bktus.com/archives/14abwa/</link>
      <pubDate>Tue, 14 Feb 2023 20:13:32 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/14abwa/</guid>
      <description>&lt;p&gt;这一周主要是确保在春节前各类服务的稳定。近期发现某个服务经常在流量高峰时段报超
时，我提醒转交服务负责人处理。但是几天过去，服务负责人依然无法说明原因。只好亲自
处理这个问题，因为报警已经十分严重，部分节点超时率能够达到 20%。&lt;/p&gt;
&lt;p&gt;在这段时间中，应该是由于临近假期，流量大幅度上涨，12 月底相比已经上涨了 100%。所
以首先是怀疑服务的承载力不足，所以先进行了一次扩容。但是，扩容后并未解决此问题，
告警频率和超时率基本未变化。这种情况下，对服务的源代码进行分析后发现，该服务的接
口会首先调用一个下游服务，然后再异步地向数据库中插入数据。因为异步操作并不阻塞工
作线程，所以首先应该怀疑是这个下游调用的问题（实际上，我在数据库那边纠结了很
久）。 从终端登录进一个节点检查日志，发现所有下游调用走的居然是同一个 IP 和端
口，并且走的是稻草人节点。所以我先将该服务做上云操作，排除稻草人转发损失造成的影
响。上云完成后，刚切流量的时候发现某个地域（不是原先的地域）下有大量超时产生，做
了扩容后也无解，十分疑惑，所以暂时切回来了。我非常奇怪，为什么上云之后，超时率却
变得更高了。&lt;/p&gt;
&lt;p&gt;从云上监控分析问题，发现在切流量后，下游服务的某个云上节点 CPU 占用非常高，而其
他的节点却很低。开始怀疑是负载均衡的问题，所以又回去检查服务的源代码。果然，该服
务从注册中心拿到下游服务可用节点列表后，只会调用列表中的第一项。所以某个地域的几
乎所有流量都集中在下有服务的某一个节点上了。而原先通过稻草人转发的时候，稻草人调
用云上节点的时候会做一次负载均衡。所以，最初的问题应该是流量大量上涨，该服务却没
有负载均衡，所以导致某个稻草人过载，进而导致超时。稻草人是代理节点本身没有逻辑，
所以能够处理的并发数更大，超时问题不是很明显。而一旦上云，流量会直接集中在某个业
务节点上，大量流量一齐涌入，会瞬间导致该业务节点大批量超时。 有了上述的论断后，
回去找稻草人的监控，发现某个稻草人确实已经过载了，CPU 占用居然达到了 95 以上。知
道原因后，接下来继续上云，先最大限度消除超时告警，然后再改代码添加随机负载均衡算
法。这样做是因为节前修改代码，流程上会比较麻烦。&lt;/p&gt;
&lt;p&gt;所以首先，我加倍了下游服务的单个节点的核数，这大大增加处理能力。然后，做切流量的
操作，一个下游节点的 CPU 占用数突然升高，最终一直保持在比其他节点高很多的比例
上，这是意料之中的事情。当整个服务平稳下来后，上云就成功了，这个时候告警已经消
除，超时率归零。接着，就是修改改服务的代码，添加负载均衡的机制，在各个流程审批通
过后为该服务发布新的代码版本。 在我发布完新版本后，下游服务的各个节点的 CPU 占用
就接近了，最终问题解决。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二三年一月第一周技术周报</title>
      <link>https://blog.bktus.com/archives/5pv1l2/</link>
      <pubDate>Fri, 20 Jan 2023 23:01:41 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/5pv1l2/</guid>
      <description>&lt;p&gt;时间进入二零二三年，今年是将一个辛苦的一年。今年将面临几方面的挑战，一个是将原先
部署在物理服务器上的数据都迁移上云。然后就是，加快培养几个团队新人，让他们尽快承
接目前的主要业务所涉及的服务，并且要求能够独立解决用户问题并对服务做出优化。这样
我就能将一些工作转交到他们名下，专注今年预估耗时较长的重要目标。还有就是，个人的
在技术和其他方面学习也到了一个攻坚阶段，这些方面决定了我未来 7~8 年的人生方向。&lt;/p&gt;
&lt;p&gt;这一周，我的主要的精力在几个服务的日志框架与日志追踪的设计与规范上。首先是解决日
志追踪的问题，为了能够跨服务地对调用过程中产生的日志进行统一的追踪，需要现将
TraceId 统一。但是目前这几个服务 TraceId 的类型层次不齐，有使用 Long 类型的也有
用字符串的。并且，这些服务所使用的语言和技术栈也不一致。直接使用一些标准的分布式
追踪框架中的 TraceId 应该无法支持所有服务目前的情况，只能用在一些技术栈比较新的
服务上。 所以，从兼容性与改造的简洁性考虑，准备采用自定义生成的 Long 类型的数值
作为 TraceId 并且限定位数为 16 位。前四位以 99 开头，作为统一 TraceId 的特征，然
后剩余两位标识服务。接下来 4 位为当前的微秒数，最后的 8 位为两组四位随机数拼接。&lt;/p&gt;
&lt;p&gt;虽然说这种 TraceId 并不能保证唯一性，但是在当前这种情况下是足够用的。如果服务为
Java 技术栈，生成 TraceId 需要充分考虑到线程竞争的情况，最好为每个线程分配一个随
机数发生器。或者，直接使用 TreadLocal。 Java 服务在处理请求时，会提取请求中的
TraceId。如果 TraceId 是 99 开头的，就不生成新的 TraceId 了。如果不是的话，按照
上述方式产生 TracId 并存储于 MDC 中。当遇到异步执行的时候，需要注意拷贝 MDC 中的
内容到旁线程，不然会丢失追踪信息。当需要调用下游服务时，需要将存储的 TaceId 传递
给下游服务。最后，当请求处理完毕时，需要清空 MDC，防止污染下一个请求的追踪信息。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二二年十二月第四周技术回顾</title>
      <link>https://blog.bktus.com/archives/4sm6qv/</link>
      <pubDate>Thu, 19 Jan 2023 19:31:54 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/4sm6qv/</guid>
      <description>&lt;p&gt;本周我感染了新冠病毒，一共在家待了 9 天。在此期间，工作上的最主要的事情是评估一
款小程序的推广上线，对我所负责的基础服务体系的影响。这款小程序切中了当时国人的需
求，预计有大量流量涌入，可能对基础服务体系的核心服务造成冲击。原先，他们有也一个
功能将要上线，流量也很大，我已经评估过并且扩容了。但是，这次还是在他们推送了上亿
的量级的通知后，发生了大批量的超时现象。 早上八点钟，躺在床上修养的我就被叫起
来，说是登录接口出现大量超时现象。&lt;/p&gt;
&lt;p&gt;我马上拿出笔记本，连上内网一看，这个接口流量直接翻了 20 多倍。我都捏了一把汗，首
先是怀疑业务容器数量不足，无法承接这么大的流量。然后通过筛选日志，发现并不是这个
问题。问题分为两个部分，其一是内部某个接口有限流，当前流量已经超出限流；另一个是
缓存数据库挂接的数据库打满。 内部接口限流比较好解决，通过紧急呼叫找到了对应的同
事调高了限流的阈值。另一个缓存数据库，由于大量老用户涌入导致不断要从数据库中读取
老数据到缓存中，而且频率随着流量的增长不断提升，最终打满了缓存后面挂接的数据库的
I/O。后续针对几个核心的缓存数据库，再次做了一批扩容，提升了缓存容量和节点数量以
应对后续更大的流量和并发。&lt;/p&gt;
&lt;p&gt;在日常维护上面，主要是将某个网关服务 Pod 的 k8s 调度策略做了调整，将其调度到由
CVM 虚拟化直接支持（一层调度）的计算节点上。原先，这个服务调度的到的计算节点是我
们公司采购的物理服务器上虚拟出来的 CVM，用作计算节点。调度到这上面以后，再于这个
CVM 上虚拟出一个执行空间（参考 Docker 技术），然后将 Pod 调度到这个节点开始运行
（二层调度）。一个计算节点上，可能存在几个甚至十几个 Pod。这些后台程序都运行于同
一台操作系统中，并且只是执行空间不同罢了。这就导致了 CPU、内存、网卡等资源的隔离
性不强，常常会互相干扰。并且当这台 CVM 计算节点需要重启或者升级的时候，其上的所
有 Pod 都会被驱逐。&lt;/p&gt;
&lt;p&gt;计算节点操作系统中的风吹草动，会影响到其上所有 Pod。这对于这种网关这种可靠性和延
迟要求苛刻的服务，来说并不合适。 而一层调度计算节点，其实是由云来分配计算资源并
虚拟出 CVM 来单独执行这个程序，CVM 资源是从整个云资源池中取得。并且这种方式支持
k8s，因为这种新的调度方式会虚拟成 k8s 上的一种“超级节点”。k8s 可以直接将 Pod 调
度到超级节点上，Pod 可以直接基于一层调度运行，也就是直接运行在一个单独 CVM 上。
这种方式隔离性强，互相之间不会受到影响。由于每个 CVM 只运行一个节点，所以当单独
一个 Pod 出现问题时，可以针对这个 Pod 的问题进行修复，而不会影响到其他 Pod。 通
过修改调度策略，将服务的所有 Pod 调度到超级节点后，整个服务运行更加稳定了。在高
峰期超时率和 CPU 占用率双高的情况也很少再出现。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二二年十二月第三周技术回顾</title>
      <link>https://blog.bktus.com/archives/kwvjou/</link>
      <pubDate>Thu, 19 Jan 2023 17:40:11 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/kwvjou/</guid>
      <description>&lt;p&gt;这一周，主要的工作是针对某个 Java 服务进行优化。该服务一直存在 CPU 占用率无法提
升上来的问题。首先考虑的问题是，该服务是否存在工作线程不足的问题。后面发现，并非
CPU 占用无法提升，而是 CPU 占用提升后会导致较多的超时问题。该服务很久以前就有反
馈性能不足，不建议继续使用。&lt;/p&gt;
&lt;p&gt;所以我感觉，这个问题来自于框架，而非业务代码。 经过对框架代码进行阅读和梳理，该
框架使用 netty 作为 NIO 服务器框架，并且会在执行业务逻辑的时候分发业务处理任务到
工作线程。然后工作线程来处理业务逻辑。之前框架有个问题就是，工作线程数太少，难以
应对高 IO 的情况。而现在的情况下，推断并非上次一样的问题，从日志来看工作线程数是
足够的。会不会是客户端的问题。在整个微服务架构下，该服务会作为客户端去调用其他服
务的接口。 这可能是一个切入点。通过阅读代码，发现该服务框架通过实现 Java 的
InvocationHandler 接口来生成代理类 ObjectProxy，该 ObjectProxy 接管对其他服务的
RPC 调用。业务代码中，通过 RPC 的方式发起对其他服务接口的调用时，ObjectProxy 会
通过它关联的 ProtocolInvoker 来获取目标服务对应有效节点列表（这个有效节点列表每
隔 30s 刷新一次）。&lt;/p&gt;
&lt;p&gt;而后，通过将列表传入负载均衡器 LoadBalancer 获得本次调用的目标节点。然后，就通过
具体协议对应的 Invoker 类向目标节点发起调用。Invoker 负责管理与目标服务之间的长
连接，在调用的时候会选取一个连接来发送请求并接收响应。具体的请求方式与此次调用类
型是异步还是同步有关。 客户端需要调用的每个目标服务由多个节点组成。对于每个节
点，该框架都会默认创建两个 I/O 线程负责网络 I/O 传输（NIO 模式）。另外，该框架会
为每个节点分别默认创建和处理器个数相当的 TCP 连接。每个 I/O 线程包含有一个
Selector 对连接的相关的事件进行轮询监听。而在每个 TCP 连接上会建立一个
TCPSession，每当需要发送一次请求时，会建立一个 Ticket 来跟踪这次请求及其关联响
应。对于同步请求来说，发送请求后会被阻塞，直到响应到来为止。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二二年十二月第二周技术周报</title>
      <link>https://blog.bktus.com/archives/mauhuw/</link>
      <pubDate>Wed, 14 Dec 2022 00:16:19 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/mauhuw/</guid>
      <description>&lt;p&gt;这一周的工作主要是对我负责的这一方面的工作的一个梳理，目前发现了许多的问题。这些
问题主要集中在数据上云方面，目前的问题主要是如何安全上云、怎么改造目前的单地域部
署方案、如何修复云下数据和云上数据之间的不一致。另外，发现还是有一些服务在使用云
下的数据库，这些云下数据库按道理是要废弃的。但是，这些服务都是一些老服务，代码改
动会带来一些风险，这就需要在行动前调查清楚。 调查的方面包括，现有的数据上云辅助
服务的基本原理和相关的代码逻辑细节，最好能够尽早发现其中存在的问题并及时修复。&lt;/p&gt;
&lt;p&gt;另外一方面，是数据上云过程需要实时监控，尽量全面地对服务接口调用质量、超时率、写
失败率、不一致率等等有个清晰的把握。这一方面最好能从上报监控和日志监控两方面来
做。而多地部署方案，目前打算采用一主多从，主从之间单方面复制，只写主库，从库只读
这几条原则入手。采用多地部署方案主要是提升服务稳定性，降低大多数请求的延迟，提升
服务质量，消除跨地域的链路不稳定带来的影响。多地部署所带来的数据同步延迟不容忽
视，必须有一个可以接受的延迟，这一块要从理论和监控两个方面来把握。 再就是，掌握
一门脚本语言很重要。特别是当有大量重复的事情需要处理，或者需要分析一些数据来获得
一个结论的时候。能够较为熟练地掌握类似 Python 这样的脚本语言，有很大的优势。但
是，如果说拿 Python 来写一个大型程序的话，我觉得是不明智的。每种编程语言就像不同
的刀，都可以拿来切菜，但是有些刀更适合用于切肉或切骨头。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二二年十二月第一周技术周报</title>
      <link>https://blog.bktus.com/archives/qqqw9n/</link>
      <pubDate>Fri, 09 Dec 2022 21:48:38 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/qqqw9n/</guid>
      <description>&lt;p&gt;这一周的工作，总结说来，主要就是将一个核心服务上云，然后不断将云下的节点切换成流
量转发节点。上云的第一步就是，在云上环境部署该服务的节点：迁移配置文件、环境，然
后根据稳定版本的代码编译适用于云上环境的镜像，然后让服务在云上环境跑起来。服务跑
起来后并且测试完成后，云上节点目前是没有任何流量的，这个时候需要将云下的部分流量
转发到云上，首先是要将云下的部分节点替换成转发节点，转发节点的作用是将主调打过来
的流量转发到云上的节点。后续可以利用这部分流量来观察云上节点的工作状态，检查异
常，可以称之为“流量灰度”。流量灰度一般控制在整体流量的 1%-5%作用，要看服务的关键
性来调整比例，测试环境下可以适当多一些，25%-50%都可以。流量灰度是发生问题时，或
者接到问题单时，只需要关闭云下的流量转发节点即可。当然，上面的一切必须先要在测试
环境操作，测试妥当了再按照同样的方案谨慎操作生产环境。 有一些后台体系错综复杂，
一次调用涉及多个服务，业务逻辑扑朔迷离，这时候尽量控制变量一段时间内仅仅做出一次
改动，等观察一段时间后，情况稳定下来了再做下一步操作。或者可以把大的步骤拆分成几
个小的步骤，一段时间内只做一小步，观察一段时间后再继续推进下一小步。这样不容易出
错。 接下来，如果灰度验证通过了（一般持续一个星期）。&lt;/p&gt;
&lt;p&gt;接下来就是切换路由了。切换路由就是将云上的服务节点的路由直接切换到云上节点，在这
以后其他云上的主调服务将直接访问该服务的云上节点，而不会再去访问云下节点。在切换
路由的时候必须特别小心，因为大量的线上流量会直接打在云上节点上。在操作之前首先，
需要根据往常数据计算云上各个地域下需要的节点数量，一般是按照高峰期流量水平来计
算，如果不够要扩容，以免由于容量不够造成线上大量超时。这个时候，云上节点数宁愿多
一些，因为多了后续还能够慢慢缩回来，成本不高。但是如果少了造成大量超时的话，节点
扩容是需要时间的（主要是资源调度与服务启动耗时），这个时候容易造成用户投诉。如果
由于超时引发客户端大量重试，就有可能带垮整个服务，引发线上事故。当时，我是挑了一
个流量少的时候操作，这样能够减少由于切换抖动造成的影响。 切换了路由后，云下节点
就可以逐渐全部换成转发节点，将云下的流量都转发到云上来处理。然后通知主调服务的负
责人，尽量把服务上云。因为，转发节点转发到云上是有开销的，会增加延迟。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二二年十一月第四周技术周报</title>
      <link>https://blog.bktus.com/archives/4a64k4/</link>
      <pubDate>Mon, 28 Nov 2022 00:47:29 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/4a64k4/</guid>
      <description>&lt;p&gt;这一周，我主要在优化一个服务。这个服务是用 Java 编写的。生产环境流量不大的时候，
也会出现调用批量超时的现象。而且发送超时的时候，CPU 占用率很低。经过观察，CPU 占
用一直就上不去。这个时候就推测是不是线程都阻塞在了某个操作上，导致这个问题。我所
接触到的大多数服务，包括这个服务，都是 IO 密集型的服务。&lt;/p&gt;
&lt;p&gt;这类服务涉及大量的 RPC 调用，当 RPC 调用的时候，工作线程会阻塞，导致无法处理其他
请求。所以这类服务的工作线程数都会设置得很大，确保有多余线程来处理 IO 请求，防止
由于大部分线程阻塞导致后续请求得不到处理，最终导致大批量超时。 这其实是有问题
的，虽然说目前 Java 在处理 Socket 和解析 Request 的时候已经采取了 NIO 的模式，但
是对于请求的逻辑处理依然采用工作线程池的方式。当遇到工作线程阻塞在 IO 请求上的时
候，这个工作线程只能等待 IO 请求完成或者超时。如果说，IO 请求所返回的结果并不是
该请求最终结果的依赖，这种情况会将请求提交到其他线程池处理。这个时候它的处理对于
该工作线程来说是异步的。&lt;/p&gt;
&lt;p&gt;最后经过排查，这个服务由于框架问题，有关于工作线程数量的配置并未被读取。这导致了
该服务启动时采取了默认的工作线程的数量设置，也就是工作线程数和 CPU 核心数相同。
所以，工作线程在处理下游 RPC 调用时，只要下游接口的耗时稍微有波动，就会导致大量
请求超时。这个时候，由于工作线程大部分时间阻塞在等待 IO 操作返回上，所以 CPU 占
用也是很少的。 如何排查的呢，首先需要在日志框架中设置打印当前线程名称，对于
logback 日志框架，就是在日志格式设置中加上%t。然后，对单个节点在测试环境进行压
测，查看在一定 QPS 下，该服务对于请求的处理情况。最好能给这个请求的逻辑代码加上
StopWatch，辅助进行分析。最后发现，输出日志的线程只有几个，不对劲。然后，使用
jstack 过滤出线程数量。发现确实只有四个。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/f9fa0b0d-8d8a-a7fa-2df4-eadfb3e171c4-2.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;可以解释一下，这个 Java 服务使用的框架采用了 netty 框架进行请求的处理，最后会转
交到 netty 的工作线程池对请求的逻辑进行处理。在这里，netty 工作线程池对应的前缀
就是 nioEventLoopGroup-5。另外可以从 cpu 累计时间来辅助证明，确实只有这 4 个线程
在处理所有的请求的主要逻辑。对于这种服务来说，生产环境下，工作线程数量一般设置为
800~1000，并且会严格设置 RPC 调用的超时时间防止大量工作线程被阻塞，最终导致节点
的吞吐量急剧下降。 在更新框架后，该问题得到了解决。另外，我还发发现了该服务的一
个主要接口涉及基于 http 协议的下游调用。该调用通过操作 OkHttp 库来进行，我发现调
用并未设置超时时间。这是错误的情况，如果遇到极端情况，下游迟迟不返回，那么工作线
程就会阻塞很久。所以，必须对下游调用设置一个合理的超时时间来保护上下游调用之间的
通畅，防止雪崩现象的发生。超时时间一般分为三种，连接超时、读超时、写超时，都需要
设置。另外，对于可能存在大量的 Http 调用情况，我开启了 OkHttp 的
ConnectionPool。&lt;/p&gt;</description>
    </item>
    <item>
      <title>搭建一个免费开源好用的Docker面板 Portainer</title>
      <link>https://blog.bktus.com/archives/qzi6jo/</link>
      <pubDate>Wed, 23 Nov 2022 20:47:20 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/qzi6jo/</guid>
      <description>&lt;p&gt;Portainer 是一个好用的 Docker 容器控制面板。它的代码仓库在&lt;a href=&#34;https://github.com/portainer/portainer&#34;&gt;这
里&lt;/a&gt;。它支持单节点和集群部署。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/8f49c1d6-b79a-d99b-36d8-7a0f0ff532fc-2.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;在此之前，我已经将个人服务器完全容器化了。如果能够可视化操作、监控各种容器，对于
日常的运维帮助很大，感觉一切尽在掌握。 可以看看搭建好后的效果，界面还是很美观
的。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/01b588ea-1159-82f3-dcb0-7992f847d3d1-2.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;可以快速拉取镜像&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/46b1c7b3-b99c-5d63-0cbb-8234d1c63d32-2.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;可以可视化发布容器，并灵活设置环境变量、网络、重启策略等等参数。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/38e2f35a-e084-a885-8322-a8918bcdbfda-2.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;可以在镜像更新的时候，快速用新镜像更新容器。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/4643c945-dad8-0874-acb0-e7890262cc90-2.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;还可以快速进入接入容器命令行，查看容器日志。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/0eedb2f6-8660-c25f-4bc2-dc10d8d400d9-2.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;可以说，我日常需要的功能都有，感觉很完善了。&lt;/p&gt;
&lt;h2 id=&#34;搭建&#34;&gt;搭建&lt;/h2&gt;
&lt;p&gt;那么对于单点服务器来说，该如何搭建呢，首先你要确认你的服务器目前有安装 Docker。
可以输入&lt;code&gt;docker -v&lt;/code&gt;来看看当前环境中是否存在 docker。 如果不存在，需要安装
docker，你可以在 Google 找找教程。对于 AWS 的 EC2，可以输入&lt;code&gt;sudo yum install docker -y&lt;/code&gt;来安装。 确认安装好 Docker 后。确认一下 Docker 是否启动。然后看看
/var/run 路径下是否有 docker.sock 文件。 然后，确认 8000 端口和 9443 端口都没有
被占用，因为 Portainer 后续要用到这两个端口。&lt;/p&gt;
&lt;h3 id=&#34;将应用数据存储在-docker-volume&#34;&gt;将应用数据存储在 Docker Volume&lt;/h3&gt;
&lt;p&gt;如果你想将 Portainer 产生的应用数据存在 Docker Volume 中，你可以直接执行下面的命
令。后续部署完成后，Portainer 所使用的 Docker Volume 也可以在 Portainer 看到并管
理。如果 8000 端口被占用了，可以将&lt;code&gt;-p 8000:8000&lt;/code&gt;改成其他端口，类似&lt;code&gt;-p 12345:8000&lt;/code&gt;。9443 端口也是类似。 如果你想指定容器名为其他，可以修改&amp;ndash;name 参数，
比如说&lt;code&gt;--name myportainer&lt;/code&gt;。&lt;/p&gt;</description>
    </item>
    <item>
      <title>二零二二年十一月第三周技术回顾</title>
      <link>https://blog.bktus.com/archives/c1vcs4/</link>
      <pubDate>Mon, 21 Nov 2022 00:07:35 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/c1vcs4/</guid>
      <description>&lt;p&gt;这是我的第一篇有关于工作中遇到的技术问题的周期性回顾，所以本期的技术回顾主要是总
结长期以来的经历，为以后的技术回顾开一个好头。 来公司工作了快半年了，最近我从客
户端开发转成了后台开发。这是我希望的，但其实不是我要求的。因为个人感觉，在中国科
技行业目前的职业生涯规划中，后台开发可以探索的东西会稍微多一些，接触问题的规模也
会大很多。其实客户端也大有可为，我的第一个比较成熟的开源项目 GpgFrontend 就是一
个客户端项目。我在其中投入了大量的时间，解决了大量的问题。尤其是编译问题、平台兼
容性问题、稳定性问题。其探索的深度，问题的难度，都是不小的。&lt;/p&gt;
&lt;p&gt;我目前觉得，为什么客户端和后端开发会被分出高下来，那是因为心没静下来，总想着往上
爬。另外，对于技术的追求本来无所谓客户端、前端或者后台，他们背后的技术思想本质上
是通用的，但是目前将职业看得太重，反而以职业分工来将技术划分地分明。我觉得这是不
好的，所以虽然我是目前是一个后台开发，但我绝不能认为我仅仅是个后台开发，其他技术
看都不看，学都不学，自己把自己的思维框起来。 现在职位转成了后台开发，我反而不知
道该怎么做了。后台开发，我目前记得，我自己写过的最早的后台项目，是我 15 岁的时候
用 Nodejs 写的一个天文论坛
&lt;a href=&#34;https://git.bktus.com/Saturneric/Stelescope&#34;&gt;Stelescope&lt;/a&gt; 。用了当时流行的
Express 框架。现在我还记得，当时第一次接触 MongoDB、登录登出的状态保存、异步回调
等等技术概念。我印象最深的是异步回调，当时用了很久才理解。因为我当时连进程、线程
的基本概念都搞得不是很清楚，更别说什么异步回调和闭包了。&lt;/p&gt;
&lt;p&gt;那时，网上还在争论 Nodejs 和 PHP 孰优孰劣，Nodejs 到底适合什么场景，然后就是异步
回调和多进程并行孰优孰劣等等。当时记得异步回调不能被阻塞，如果遇到阻塞操作会使用
一种非阻塞的 API，这种 API 能够立即返回，将阻塞操作放到一边处理，主线程依然能够
继续处理后续的代码。等阻塞操作处理完了，就会通知主线程执行回调函数来处理阻塞操作
的结果。 后续，我还接触了 Python 的后台开发，写了一个简单的班级学业考勤管理系统
（&lt;a href=&#34;https://git.bktus.com/Saturneric/SP&#34;&gt;SP&lt;/a&gt;）。在这里，我接触了 MVC 的思想，我理
解为模型、视图和控制器。这是一种重要的思想，那时候前端的概念还不是很明细，前后端
分离还不是主流思想。在当时，服务器负责动态页面的生成，由请求触发控制器做出响应。
控制器基于模型进行计算，并最终通过模板引擎将模型渲染成页面，而后页面被返回到用户
浏览器。就这么一个过程。记得当时，会在服务端定义很多模板，模板里选一些地方镂空，
待会存放数据。或者是定义一个小的卡片控件，放在 for 语句中，待会用模板引擎生成出
很多卡片出来。在当时，我作为后台开发要考虑方方面面，包括页面漂不漂亮，数据安全，
响应快不快等等。&lt;/p&gt;
&lt;p&gt;然后大一下开始，我就接触了 Spring 框架，具体用的就是 SpringBoot。这个时候，才真
正了解到了关系型数据库。原来我对于关系型数据库的理解，仅仅是会安装，配置。记得很
深刻，当时接触到了前后端分离的思想，觉得这是个好东西。拿出来和王老师讨论，说我们
的全员育人管理系统用前后端分离最好。王老师非常开明，和我聊了很多，同意了我的方
案。前后端分离，顾名思义，就是将动态页面的渲染放到用户那边，服务器仅仅负责数据的
处理和存储。这样有助于分工和解耦，虽然当时网上也有很多质疑的声音，我还是觉得这是
趋势。当时害痴迷于一种 RestfulAPI 的接口规范，觉得如果这样做我们连写项目文档也可
以免了。但是现实很骨感，在实践中对于一些复杂的情况就难以保持 RestfulAPI 的风格。
通过与 SpringBoot 打交道，我学会了很多有关后台的东西，目前我也在用这些原来的经
验。我在大学本科生涯中，写了很多的 SpringBoot 项目。到现在，我进了公司发现部门的
技术栈就是 Java，新的项目用的框架都是 SpringBoot，反倒用上了。虽然说我当时很厌恶
Java，觉得它臃肿与繁琐，包括现在也没有什么好感，但是 Java 的生态确实是很强大的，
想找个什么组件很容易，而且 Java 组件都是成熟的、良好维护的并且文档齐全。Java 技
术栈对于面向生产的后台项目来说，确实是个省心、好找工作的技术栈。&lt;/p&gt;</description>
    </item>
    <item>
      <title>知识的相对性和条件性</title>
      <link>https://blog.bktus.com/archives/7gmavw/</link>
      <pubDate>Wed, 09 Nov 2022 22:37:35 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/7gmavw/</guid>
      <description>&lt;p&gt;&lt;strong&gt;本文是 AI 基于&lt;a href=&#34;https://blog.bktus.com/archives/0tui6f&#34;&gt;原文&lt;/a&gt;分析后生成的。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;拥有广泛而深入的知识对个人发展至关重要，因为它不仅提升了我们的思维深度，还增强了
我们处理复杂问题的能力。知识的获取并不是简单地吸收外部信息，而是需要经过个人的深
思熟虑和批判性分析。在这个过程中，理解知识的相对性和条件性变得尤为重要。&lt;/p&gt;
&lt;h2 id=&#34;知识的相对性和条件性&#34;&gt;知识的相对性和条件性&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;知识的不确定性&lt;/strong&gt;：历史上许多被认为是不变真理的知识，随着时间的推移和科学的
发展，被新的发现所颠覆。例如，牛顿力学被认为是解释物理现象的绝对框架，直到爱
因斯坦的相对论的出现。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;知识的多元性&lt;/strong&gt;：在不同文化和社会中，知识和真理的理解各有差异。例如，东西方
哲学传统在对待知识和真理的问题上就有很大的不同。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;知识应用的重要性&#34;&gt;知识应用的重要性&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;理论与实践的结合&lt;/strong&gt;：理论知识如果不能应用于实际生活中，其价值便大打折扣。应
用知识解决实际问题是知识价值的重要体现。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;知识转化为智慧&lt;/strong&gt;：通过个人经验和深思的过程，知识可以转化为智慧。这种转化使
我们能够更有效地解决问题，对复杂的生活和工作环境有更深的理解和应对能力。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;成功的个性化路径&#34;&gt;成功的个性化路径&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;成功方法的多样性&lt;/strong&gt;：没有普适的成功方法。每个人的背景、经历和目标都不同，因
此，成功的路径也应该是个性化的。例如，一些企业家通过独特的方法找到了商业成
功，而艺术家则通过自己独特的风格表达自己的创意。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;适应环境的变化&lt;/strong&gt;：变化是生活的常态。我们需要根据环境的变化不断调整自己的方
法和策略。例如，在快速变化的科技领域，不断学习新技能和适应新趋势是成功的关
键。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;结论&#34;&gt;结论&lt;/h2&gt;
&lt;p&gt;综上所述，知识的积累和应用对于个人的成长和成功至关重要。我们需要认识到知识的相对
性和条件性，通过批判性思考和深度分析来吸收和应用知识。同时，我们也要理解成功没有
统一的模式，每个人都需要根据自己的情况创造适合自己的成功路径。在这个过程中，保持
对知识的开放态度和适应环境变化的能力是关键。通过这种方式，我们可以更有效地应对生
活中的挑战，实现个人目标。&lt;/p&gt;</description>
    </item>
    <item>
      <title>浅论专注于目标并尝试实现它</title>
      <link>https://blog.bktus.com/archives/dv99w5/</link>
      <pubDate>Wed, 09 Nov 2022 22:36:08 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/dv99w5/</guid>
      <description>&lt;p&gt;&lt;strong&gt;本文是 AI 基于&lt;a href=&#34;https://blog.bktus.com/archives/er6eer&#34;&gt;原文&lt;/a&gt;分析后生成的。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;论述&#34;&gt;论述&lt;/h2&gt;
&lt;p&gt;在我们追求目标的旅途中，常常希望能迅速实现这些目标，但这种心态往往会导致我们感到
急躁和焦虑。相反，我们应该培养一种内心的平和和耐心，同时在心中保持对目标的清晰认
识。通过这种方式，我们可以保持冷静，减少外界干扰，从而更加全面和周密地规划我们的
行动，增加成功的可能性。 在采取行动的过程中，专注是至关重要的。我们需要全神贯
注，集中精力于目标上。只有这样，我们才能发挥出全部的潜力和思考能力，从而在所追求
的领域中更加专业和专注。为了实现这一点，我们需要在行动之前对目标进行充分的了解和
思考，制定出科学合理的行动计划。当我们的思路清晰，计划周到时，我们的心思就能更加
集中，减少被杂念和外部干扰的可能性。 最后，成功的实现还需要耐心和毅力。在追求目
标的过程中，我们需要保持平和的心态，避免焦虑和急躁。在行动过程中，我们应不断地总
结经验，调整策略，从而稳步推进，达成最终的成功目标。 这种方法不仅适用于个人目标
的追求，也适用于更广泛的领域，如学术研究、职业发展甚至是艺术创作。在这些领域中，
心境的平和、行动的专注和过程中的耐心同样是成功的关键要素。通过这种方式，我们不仅
能够更有效地达成目标，还能在过程中发现更多的乐趣和价值，使得整个旅程成为一种丰富
和有益的经历。&lt;/p&gt;
&lt;h2 id=&#34;论证&#34;&gt;论证&lt;/h2&gt;
&lt;p&gt;追求目标的过程中保持内心平静、专注以及耐心的重要性可以从哲学和心理学的角度得到深
入的论证。&lt;/p&gt;
&lt;h3 id=&#34;哲学角度&#34;&gt;哲学角度&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;斯多葛哲学&lt;/strong&gt;：斯多葛学派强调内心的平和与自我控制。他们认为，通过理性控制情
绪，人可以达到一种内心的平静和满足。这种心态有助于我们在追求目标时保持冷静和
客观，避免被短期的情绪波动干扰。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;亚里士多德的中庸之道&lt;/strong&gt;：亚里士多德提出的中庸之道强调在行为和情感上寻找适
度。过度急躁或过分冷漠都不利于目标的实现。保持平衡的情绪和行动是达成目标的关
键。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;心理学角度&#34;&gt;心理学角度&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;心流理论&lt;/strong&gt;：心理学家米哈伊·契克森米哈伊的心流理论指出，在完全专注于一项活
动时，个人可以达到最佳的心理状态，即“心流”。在这种状态下，人们不仅能够最大限
度地发挥潜能，还能从活动中获得极大的满足和快乐。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;目标设定理论&lt;/strong&gt;：根据心理学家埃德温·洛克的目标设定理论，明确且具有挑战性的
目标更容易激发个人的动力。同时，持续的关注和耐心是实现这些目标的关键。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;实践中的应用&#34;&gt;实践中的应用&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;冥想和自我反省&lt;/strong&gt;：定期进行冥想和自我反省可以帮助个人发展内心的平静和专注
力。这些实践有助于提升我们在面对挑战时的心理韧性和专注能力。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;长期目标与短期行动的平衡&lt;/strong&gt;：在追求长期目标的同时，设定可实现的短期目标可以
帮助我们保持动力和专注。这种方法可以使我们在追求目标的过程中保持耐心，逐步取
得进展。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;结论&#34;&gt;结论&lt;/h3&gt;
&lt;p&gt;从哲学和心理学的角度来看，内心的平静、专注和耐心对于成功追求和实现目标至关重要。
这些心理状态不仅有助于我们在追求目标的过程中保持清晰的思路和有效的行动，而且能够
使我们在这个过程中保持积极的心态和心理健康。通过实践这些原则，我们可以在个人成长
和目标实现的旅程中获得更多的满足和成就感。&lt;/p&gt;</description>
    </item>
    <item>
      <title>浅论知行合一</title>
      <link>https://blog.bktus.com/archives/8zkrzg/</link>
      <pubDate>Wed, 09 Nov 2022 22:35:03 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/8zkrzg/</guid>
      <description>&lt;p&gt;&lt;strong&gt;本文是 AI 基于&lt;a href=&#34;https://blog.bktus.com/archives/9h5dq9&#34;&gt;原文&lt;/a&gt;分析后生成的。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在现实行动中，我们常常误以为仅凭掌握知识就足以保证成功。然而，实际情况远比我们的
理论复杂得多。事物的变化和不确定性是常态，这些变化往往会成为我们实际行动中的障
碍。因此，我们在行动时必须保持谨慎，以应对可能出现的意外情况。&lt;/p&gt;
&lt;h3 id=&#34;知识与行动的不一致性&#34;&gt;知识与行动的不一致性&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;知识的局限性&lt;/strong&gt;：我们通常认为知识等同于成功的保障，但这只是一种理想化的想
法。实际上，我们所学习的知识通常基于理论和主观想象，这些知识很难涵盖所有可能
的情况和细节。因此，成功的实现需要我们在实践中不断尝试和积累经验。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实践中的挑战&lt;/strong&gt;：在实际行动过程中，我们经常会遇到各种挑战和反对意见。面对这
些批评，我们既不能盲目接受，也不能完全忽视。适当倾听他人的意见，并结合自己的
情况进行反思，是达成成功的重要环节。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;批判性思维的重要性&#34;&gt;批判性思维的重要性&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;对他人意见的审慎处理&lt;/strong&gt;：他人提供的建议或批评可能基于他们自身的经验和视角，
这些可能并不完全适用于我们的具体情况。在接受建议时，我们需要审慎考虑，并结合
自己的实际情况作出决策。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实践与验证&lt;/strong&gt;：通过实际行动检验自己的知识和决策的正确性是非常重要的。只有通
过实践，我们才能真正地理解知识的应用和自己决策的有效性。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;持续的自我提升&#34;&gt;持续的自我提升&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;应对变化和挑战&lt;/strong&gt;：成功的路径并不是一成不变的。我们需要根据自己的实际情况和
遇到的具体挑战灵活调整行动策略。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不断学习和成长&lt;/strong&gt;：在不断的行动过程中，我们应该持续地学习新知识，提升自己的
能力和技巧，以更好地应对不断变化的环境和挑战。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;结论&#34;&gt;结论&lt;/h3&gt;
&lt;p&gt;综上所述，虽然知识是成功的重要基础，但实际行动中的成功取决于我们如何应用这些知
识，并根据实际情况不断调整和完善自己的行动策略。保持谨慎、开放的心态，不断地学习
和实践，以及有效地整合外界的意见和反馈，是走向成功的关键。通过这种方式，我们不仅
能够应对眼前的挑战，还能为未来的成功打下坚实的基础。&lt;/p&gt;</description>
    </item>
    <item>
      <title>论什么是事物本质</title>
      <link>https://blog.bktus.com/archives/219pfm/</link>
      <pubDate>Wed, 09 Nov 2022 22:33:17 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/219pfm/</guid>
      <description>&lt;p&gt;&lt;strong&gt;实际发表时间：2018-05-25 &lt;a href=&#34;https://blog.bktus.com/archives/3794&#34;&gt;原文&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在日常生活中，我偶然开始书写这些文字。写作对我来说，不仅是一种心灵的抚慰，更是一
种思考的深化。通过书写，我能够整理自己的思绪，静下心来深思。这些文字仿佛是一套哲
学的装备，既是理论的锐利武器，也是坚固的防御盾牌。它们帮助我面对生活中的挑战和困
惑，其中包括知行论的思考。这些想法源于我的日常生活、阅读的书籍和个人的反思。&lt;/p&gt;
&lt;h3 id=&#34;感官知识的局限性&#34;&gt;感官知识的局限性&lt;/h3&gt;
&lt;p&gt;在我们试图理解一个对象时，我们通常会依赖自己的感官，例如用眼睛观察、用耳朵聆听、
用手触摸来感受其质感。我们往往认为，通过感官的作用，我们能够捕捉到该对象的存在和
特性。 然而，我们的感官只能捕获有限的信息，并且这些信息可能会受到感官自身的局限
性和外界环境的影响。因此，我们无法完全确定自己感知到的是否代表了对象的真实本质。
更深入地探讨，如果存在一种与我们的感官系统截然不同的感官系统，那么它所感知到的对
象可能与我们的感知完全不同。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;康德的感官知识论&lt;/strong&gt;：康德在其《纯粹理性批判》中指出，我们的感官知识受到时间
和空间这两个先验条件的限制，我们所能感知的只是事物的现象，而非其自身。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;赫拉克利特关于变化的观点&lt;/strong&gt;：古希腊哲学家赫拉克利特曾说：“万物流转，无物常
在。”这意味着我们的感官所捕捉的只是事物不断变化的状态，而非其恒定的本质。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;思维的主观性和文化相对性&#34;&gt;思维的主观性和文化相对性&lt;/h3&gt;
&lt;p&gt;此外，我们的思考也受到我们的经历、背景和价值观等因素的影响。因此，我们对问题的思
考可能基于自身的视角，而不一定能深入到对象的本质。即使我们认为自己的思考已经很深
入，实际上它也可能仅仅是基于我们对对象的感官经验和个人偏好的理解。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;黑格尔的辩证法&lt;/strong&gt;：黑格尔的辩证法认为，真理是通过对立统一的过程中不断展开
的。我们的思维受限于当前的知识结构和文化背景，因此总是处于发展和变化之中。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;萨特的存在主义&lt;/strong&gt;：萨特认为，人是自由而孤立的存在，我们的思考和价值观是主观
构建的。我们对事物的理解是基于个人的经验和选择，而非客观的真理。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;知识的传递与解构&#34;&gt;知识的传递与解构&lt;/h3&gt;
&lt;p&gt;最终，我们接触到的知识也往往来源于他人的思维和传授。因此，我们所理解的对象可能仅
仅是从某些特定角度去解读，而并不一定是对象本身的真实本质。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;达尔文的进化论&lt;/strong&gt;：在生物学上，达尔文的进化论指出，知识和能力的传递是一个适
应环境的过程。这同样适用于文化和知识的传递，知识不断地适应和改变。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;德里达的解构主义&lt;/strong&gt;：德里达的解构主义强调文本和语言的多义性，主张解构固有的
意义结构，揭示知识传递中的隐含偏见和局限性。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;结论&#34;&gt;结论&lt;/h3&gt;
&lt;p&gt;综上所述，我们的感知和思考是复杂且多层次的。它们不仅受限于感官的局限性，还受到个
人经验、文化背景和思维方式的影响。因此，我们对事物的认识总是部分的、主观的，并且
不断变化。这些哲学理论提醒我们，对知识的追求应当是一个不断探索、质疑和重构的过
程，而非寻求一个确定无疑的终极真理。通过这种方式，我们可以更加深刻和全面地理解周
围的世界，并在这个过程中发现自身的价值和位置。&lt;/p&gt;</description>
    </item>
    <item>
      <title>论心理上的一种“反质变”现象</title>
      <link>https://blog.bktus.com/archives/jiuc9z/</link>
      <pubDate>Wed, 09 Nov 2022 22:25:09 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/jiuc9z/</guid>
      <description>&lt;p&gt;&lt;strong&gt;本文是 AI 基于&lt;a href=&#34;https://blog.bktus.com/archives/rr970y&#34;&gt;原文&lt;/a&gt;分析后生成的。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;理解反质变的现象，需要深入探讨其背后的心理和哲学机制。反质变不仅是一个简单的心理
反应，而是一个涉及复杂情感、信念和认知的过程。它揭示了人类认知的深层结构，以及我
们如何处理信息和情感的方式。这种现象在日常生活中无处不在，从我们对人际关系的理解
到我们对世界的看法，都可能受到反质变的影响。&lt;/p&gt;
&lt;h3 id=&#34;反质变的心理动力学&#34;&gt;反质变的心理动力学&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;认知失调理论&lt;/strong&gt;：心理学家列昂·费斯廷格提出的认知失调理论解释了个人在面对矛
盾信息时的心理状态。当我们的信念与新的信息冲突时，可能会产生心理不适。在某些
情况下，为了减少这种不适，个人可能会改变原有的信念，这就是反质变的心理基础。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;信任的脆弱性&lt;/strong&gt;：信任建立在一系列复杂的心理过程之上，包括预期、信念和情感。
当这些预期被打破时，信任可能会迅速崩溃。这种崩溃不仅是对特定事件的反应，也是
对整个信任体系的重估。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;哲学视角下的反质变&#34;&gt;哲学视角下的反质变&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;康德的认知论&lt;/strong&gt;：康德在其作品中探讨了人类认知的限制。他认为，我们对事物的认
识受限于我们的感官和理性。在反质变的过程中，我们可能会意识到之前的认知是有限
的，从而导致信念的根本改变。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;萨特的自由意志&lt;/strong&gt;：萨特的存在主义哲学强调自由意志的重要性。他认为，人是自由
选择自己生活方式的。在反质变的过程中，这种自由意志可能被激活，促使个人重新评
估并选择不同的信念和行为模式。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;反质变的社会文化因素&#34;&gt;反质变的社会文化因素&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;文化相对主义&lt;/strong&gt;：不同的文化背景可能导致对同一事件的不同解读。在一个文化中被
视为信任破裂的事件，在另一个文化中可能被视为正常。这种文化差异可能影响个人对
事件的解读和反应。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;社会认同理论&lt;/strong&gt;：社会心理学家提出的社会认同理论指出，个人的自我认同部分基于
其所属的社会群体。当这些群体的信念或行为发生变化时，个人的认同也可能发生改
变，从而导致反质变。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;反质变的实际应用&#34;&gt;反质变的实际应用&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;心理健康&lt;/strong&gt;：理解反质变的心理过程对于心理健康领域至关重要。它有助于心理学家
和治疗师更好地理解和处理人们在面对重大生活事件时的心理反应。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;冲突解决&lt;/strong&gt;：在社会和政治冲突中，理解各方的反质变过程可以帮助中介者和冲突解
决者更有效地解决争端。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;结论&#34;&gt;结论&lt;/h3&gt;
&lt;p&gt;总的来说，反质变的现象揭示了人类认知和情感的复杂性。在理解和处理信任、信念和情感
方面，我们需要认识到这些变化的非线性和不可预测性。对于反质变的深刻理解可以帮助我
们更好地理解人类心理和行为的复杂性，以及在个人和社会关系中如何更有效地建立和维护
信任。&lt;/p&gt;</description>
    </item>
    <item>
      <title>有关下一阶段的计划</title>
      <link>https://blog.bktus.com/archives/ypbzh5/</link>
      <pubDate>Wed, 09 Nov 2022 22:23:59 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/ypbzh5/</guid>
      <description>&lt;p&gt;&lt;strong&gt;实际撰写时间：2017-05-20 20:57:23&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不得不承认，去年是一个低落的一年，不管是生活上，学习上，还是精神上。眼看着和目标
渐行渐远，自己又无力改变。&lt;/p&gt;
&lt;p&gt;但是，现在不同了。在度过了种种困难后，终于在艰难种找到了一种新的思考问题的方式，
也第一次发现了自我。在解决了一系列问题后，内忧趋于瓦解，我觉得，终于可以集中自己
的所有能力而不会受制于自己本身了。&lt;/p&gt;
&lt;p&gt;该找到的答案，我已经找到了。这个时候，内心感到宁静。是时候开始奔跑了。学会奔跑的
我，再也不会是被自己折磨苟且爬着和别人比赛的我。在我学会奔跑后，被我超越的，再也
不可能赶超回来。&lt;/p&gt;</description>
    </item>
    <item>
      <title>自己总结出养成习惯的一些实用经验</title>
      <link>https://blog.bktus.com/archives/chxt92/</link>
      <pubDate>Sat, 23 Apr 2022 03:41:18 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/chxt92/</guid>
      <description>&lt;p&gt;很多人都会想养成一个好习惯，因为一个好习惯能够然仍长期做一件好的事情。这件好的事
情，每做一次都会带来一定的好的影响。而一个好的影响的一次次叠加，经过比较长的一段
时间，就能使得一个人的某个方面产生巨大的良性改变。而很多人想养成习惯却难以坚持下
来。反而求助于很多外力来“监督”自己，这样反倒让自己变得更加痛苦。 我觉得想养成习
惯而不得根本原因是缺乏内在的强大的动机。比如说，你想学习一门外语。你知道，学一门
外语能够有种种好处。但是，你其实内心清楚，这些好处只不过是锦上添花，并不会影响你
的前途。自己是骗不了自己的，我这里不是要说要不断暗示自己学习一门外语很重要。&lt;/p&gt;
&lt;p&gt;我这里想建议，你要让学习一门外语真的对你来说很重要，这才是有效的。比如说，你报了
一个出国留学的计划，是你人生规划的一部分，花了很多钱签订了合同。你现在是不学也不
行了，不学，你的人生计划就完不成，为了签订合同所花费的钱也打了水漂。这样，才会产
生强大的内驱力。这种内驱力一旦产生，它会在你的内心不断提醒你，不断鞭策你，让你自
动去拿起外语书。除非，你有什么拒绝它的理由，不然你的怠惰在你自己这里就过不了关。
另一个我发现的重要一点是，习惯的订立要顺应自然，最主要的是要顺应自己的内心。不能
说，给自己定一个自己不喜欢的习惯。你不喜欢某件事情，你非要去强迫自己做，那最终是
做不成的。喜不喜欢一件事情，主要看你先做这件事情前会不会有一种愉悦感，你能想到你
做这件事后，你能收获什么，这让你感到愉悦。有一种愉悦感，能够时不时地提醒你去做一
件事。 第三点，长期坚持而非一直坚持。不能说要强迫自己一直坚持某种习惯，因为随着
自己生活的继续，习惯是会被慢慢改变的。长期坚持，这意味着在一段很长的时间内，你是
会经常做这个事情的。&lt;/p&gt;
&lt;p&gt;偶尔的一两次没有做，不代表习惯没有了或者是习惯被打破了。因为事务的发展不是一帆风
顺的，总有反复。所以给自己一点做不一样事情或者不做这件事情的时间，让自己处于一种
比较放松的状态。记住，盈满则亏，让自己总是游刃有余一些，容许一些小的偷懒，养成习
惯的过程中就不会出现大的报复性波动。在养成习惯的过程中，你可能会发现这个习惯并不
是一个好习惯，或者并不适合你。这个时候请果断放弃这个习惯。因为养成习惯是一个正向
反馈，是自己不断激励自己，不断有所收获，而不是一个自己和自己内心拉扯的过程。 还
有一点就是，习惯的养成不能影响自己的正常作息。不能说我今天要背单词，由于一些突发
情况没有做成，然后在深夜也要背完，挤占了自己的睡觉时间。这是得不偿失的，反而会因
为自己的生活周期的失调，陷入一种疲于奔命的情况，导致习惯越来越难以养成。&lt;/p&gt;
&lt;p&gt;最后，如何知道一个习惯是否已经养成？当你发现，你今天不做这件事情的时候，好像缺了
点什么的时候。或者，某个时间会自动地想起去做这件事的时候。这个时候就可以认为习惯
养成了，你只要顺着来，享受习惯的惯性带给你的快乐，在这个过程中，你就能不断收获自
己在某一方面的成长和快乐。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Ubuntu双系统重装Windows后修复grub2引导  UEFI</title>
      <link>https://blog.bktus.com/archives/k3xpne/</link>
      <pubDate>Fri, 26 Nov 2021 11:51:13 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/k3xpne/</guid>
      <description>&lt;p&gt;如果你在安装了 Ubuntu 和 Windows 双系统后，又重装了 Windows 系统。那么 Grub 引导
项大概率会被 Windows Boot Manager 覆盖，这时候你就进不了 Ubuntu 了。但不要慌，按
照下面的步骤可以修复 grub2 引导，而且不需要安装额外的软件。&lt;/p&gt;
&lt;h2 id=&#34;制作-ubuntu-的-u-盘启动盘&#34;&gt;制作 Ubuntu 的 U 盘启动盘&lt;/h2&gt;
&lt;p&gt;为了修复引导项，我们需要用到 Ubuntu 系统提供的软件工具。虽然我们暂时进不去原来的
Ubuntu 系统，但是我们可以使用写在 Ubuntu U 盘中的镜像来获得一个可用的基本 Ubuntu
环境。 在&lt;a href=&#34;https://ubuntu.com/download/desktop&#34;&gt;Ubuntu 官网&lt;/a&gt;下载镜像文件。
&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/c504c695-aa38-05e7-19f4-879f896c56ad-2.webp&#34;&gt;
制作 U 盘启动盘可以使用免安装、小巧好用的&lt;a href=&#34;https://rufus.ie/zh/&#34;&gt;rufus&lt;/a&gt;。你可以使
用 rufus 快速创建一个 U 盘启动盘，注意选择 GPT 模式。
&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2/2025/04/28/61cd20f7-cee4-cdc6-de00-9bd832b81613-2.webp&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;引导-u-盘启动盘&#34;&gt;引导 U 盘启动盘&lt;/h2&gt;
&lt;p&gt;重启电脑，在 BIOS 引导设置中引导 U 盘，然后进入 Ubuntu 引导安装程序后，在安装界
面选择 Try Ubuntu 进入 Ubuntu Live。&lt;/p&gt;
&lt;h2 id=&#34;执行-grub2-重建操作&#34;&gt;执行 Grub2 重建操作&lt;/h2&gt;
&lt;p&gt;使用 fdisk，找到 EFI 分区，/boot 挂载点所在的分区（如果你没有设置/boot 挂载点则
为/挂载点）。 挂载/boot 挂载点所在的分区到/mnt 下（我的分区在 nvme 固态硬盘
上）。&lt;/p&gt;</description>
    </item>
    <item>
      <title>解决yarn安装electron、chromedriver等软件包超时、缓慢的问题</title>
      <link>https://blog.bktus.com/archives/fs5oy3/</link>
      <pubDate>Mon, 22 Nov 2021 15:14:14 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/fs5oy3/</guid>
      <description>&lt;p&gt;在国内使用 yarn 安装 electron、chromedriver 是经常出现无法连接的问题，这个时候，
相对于设置代理，我们可能更希望使用在国内的镜像仓库来加速这个过程。并且安装
electron 的时候，单单设置 yarn 的全局代理是没有用的。那如何根据不同的软件包设置
代理呢？你可以按照以下列表中提供的命令样例来设置。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2025/05/05/01209ec0-4f98-56db-4453-f1074273e7a5.webp&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;yarn-全局设置&#34;&gt;yarn 全局设置&lt;/h2&gt;
&lt;p&gt;设置 yarn 安装一般的软件包时使用的仓库地址。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;yarn config set registry https://r.npm.taobao.org 注册模块镜像
yarn config set disturl https://npm.taobao.org/dist # node-gyp 编译依赖的 node 源码镜像
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是运行以上命令的结果，你可以很清楚地看到设置是否成功。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2025/05/05/6a35e2d0-9204-3dbb-3565-d2ad83c52cc5.webp&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;yarn-安装特定软件包设置&#34;&gt;yarn 安装特定软件包设置&lt;/h2&gt;
&lt;p&gt;设置 yarn 安装 electron 、chromedriver 等软件包安装使用到的仓库地址。你可以按照
需要选择一两个命令来设置，一股脑全部加上是被必要的。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;yarn config set sass\_binary\_site https://npm.taobao.org/mirrors/node-sass # node-sass 二进制包镜像
yarn config set electron\_mirror https://npm.taobao.org/mirrors/electron/ # electron 二进制包镜像
yarn config set puppeteer\_download\_host https://npm.taobao.org/mirrors # puppeteer 二进制包镜像
yarn config set chromedriver\_cdnurl https://npm.taobao.org/mirrors/chromedriver # chromedriver 二进制包镜像
yarn config set operadriver\_cdnurl https://npm.taobao.org/mirrors/operadriver # operadriver 二进制包镜像
yarn config set phantomjs\_cdnurl https://npm.taobao.org/mirrors/phantomjs # phantomjs 二进制包镜像
yarn config set selenium\_cdnurl https://npm.taobao.org/mirrors/selenium # selenium 二进制包镜像
yarn config set node\_inspector\_cdnurl https://npm.taobao.org/mirrors/node-inspector # node-inspector 二进制包镜像
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;和上面的类似，运行命令后你可以很清楚地看到设置是否成功。&lt;/p&gt;</description>
    </item>
    <item>
      <title>oh my zsh 在Ubuntu下的配置教程</title>
      <link>https://blog.bktus.com/archives/2hlujj/</link>
      <pubDate>Mon, 22 Nov 2021 15:04:56 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/2hlujj/</guid>
      <description>&lt;p&gt;oh my zsh 是十分好用的基于 zsh 的配置框架，它能简化 Linux 终端用户的很多日常操
作。而且，它的界面相对于原始的 bash 来说，非常好看。这篇文章就是用来介绍如何在
Ubuntu 下安装并配置 oh my zsh 及其常用插件的。&lt;/p&gt;
&lt;h2 id=&#34;oh-my-zsh-安装与基本配置&#34;&gt;oh my zsh 安装与基本配置&lt;/h2&gt;
&lt;p&gt;在 oh my zsh 安装前需要先执行以下命令安装下列 git、curl、zsh。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% sudo apt install git curl zsh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;安装完依赖项目后，直接执行下面的命令来一键安装：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% sh -c &amp;#34;$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;设置 zsh 为默认 shell：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% chsh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;按照提示一步一来，输入/bin/zsh 即可。&lt;/p&gt;
&lt;h2 id=&#34;常用插件安装&#34;&gt;常用插件安装&lt;/h2&gt;
&lt;p&gt;单单配置 oh my zsh 本身是远远不够的，你可能需要以下常用插件来真正达到简化操作的
目的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;z 历史目录管理&lt;/li&gt;
&lt;li&gt;zsh-autosuggestions 命令提示&lt;/li&gt;
&lt;li&gt;zsh-syntax-highlighting 高亮&lt;/li&gt;
&lt;li&gt;sudo 忘记加 sudo 前缀之时&lt;/li&gt;
&lt;li&gt;extract 一个命令解压几乎所有安装包&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;z&#34;&gt;z&lt;/h3&gt;
&lt;p&gt;无需额外安装，直接在 plugins 中填写即可。&lt;/p&gt;
&lt;h3 id=&#34;zsh-autosuggestions&#34;&gt;zsh-autosuggestions&lt;/h3&gt;
&lt;p&gt;先执行以下命令，然后在 plugins 中填写。&lt;/p&gt;</description>
    </item>
    <item>
      <title>使用 space-vim-dark 一键配置、美化vim编辑器</title>
      <link>https://blog.bktus.com/archives/wwztim/</link>
      <pubDate>Mon, 22 Nov 2021 14:33:41 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/wwztim/</guid>
      <description>&lt;p&gt;一直以来我都使用一些成熟的配置文件来帮助我配置、美化 vim 编辑器，然而我原来使用
的 spf13-vim.sh 已经很久不更新了，它的插件列表中有些插件已经不能正常下载了。所以
我想寻找它的替代品，最后发现 space-vim-dark 还不错。&lt;/p&gt;
&lt;h2 id=&#34;space-vim-dark-基本介绍&#34;&gt;space-vim-dark 基本介绍&lt;/h2&gt;
&lt;p&gt;经过我的寻找，找到了一个比较好用且美观的配置文件 space-vim-dark。这个
space-vim-dark 可能是国人编写的 vim 配置文件，它能很好使得 vim 适应暗色模式。 先
贴出仓库地址：https://github.com/liuchengxu/space-vim-dark 这是它的效果图，整体
看还是不错的。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;配置vim编辑器的效\n果&#34; loading=&#34;lazy&#34; src=&#34;https://image.cdn.bktus.com/i/2025/05/05/a84e404a-54ea-5d41-549e-24f225375c5c.webp&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;用它配置美化-vim-编辑器&#34;&gt;用它配置、美化 vim 编辑器&lt;/h2&gt;
&lt;p&gt;设置 space-vim-dark 非常简单，你只需要在你的 vim 插件管理器中添加下面的设置。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Plug &amp;#39;liuchengxu/space-vim-dark&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;整体使用下来，我觉得该有的插件还是有的，并且用起来顺手不少。&lt;/p&gt;
&lt;h2 id=&#34;加入额外配置&#34;&gt;加入额外配置&lt;/h2&gt;
&lt;p&gt;在~/.spacevim 中可以加入你自己的一些配置。&lt;/p&gt;</description>
    </item>
    <item>
      <title>求解三维装箱问题的混合模拟退火算法的实现 MATLAB</title>
      <link>https://blog.bktus.com/archives/kl9byw/</link>
      <pubDate>Thu, 30 Sep 2021 17:02:00 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/kl9byw/</guid>
      <description>&lt;p&gt;由于要数学建模中需要解决一个三维装箱的问题，我经过搜寻选定了张德富教授等在计算机
学报上发表的《求解三维装箱问题的混合模拟退火算法》这篇论文作为解决问题的理论基
础。&lt;/p&gt;
&lt;h3 id=&#34;该论文的摘要如下&#34;&gt;该论文的摘要如下：&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;提出了一个高效求解三维装箱问题(Three Dimensional Container Loading Problem
3D-CLP)的混合模拟 退火 算法 .三维装箱问题要求装载给定箱子集合的一个子 集到容器
中 , 使得被装载 的箱子总体 积最大 .文中介绍 的 混合 模拟退火算法基于三个重要算
法 :(1)复合块生成算法 , 与传统算法 不同的是文中提出的复合块 不只包含单 一 种类
的箱子 , 而是可以在一定的限制条件下包含 任意种类的箱子 .(2)基础启发式算法 , 该
算法 基于块装 载 , 可以 按 照指定装载序列生成放置方案.(3)模拟退火算法,以复合块
生成和基础启发式算法为基础, 将装载序列作为可行 放置 方案的编码 , 在编码空间中
采用模拟退火算法进行搜 索以寻找问题的近似最 优解 .文 中采用 1 50 0 个弱异构 和
强异构的装箱问题数据对算法进行测试 .实验结 果表明 , 混合模拟退火算法的填充率超
过了目前已知的 优秀算法 .&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;DOI号: 10.3724/SP.J.1016.2009.02147&lt;/p&gt;</description>
    </item>
    <item>
      <title>TransRepair: Automatic Testing and Improvement of Machine Translation（机器翻译的自动化测试和改进）</title>
      <link>https://blog.bktus.com/archives/f6adzy/</link>
      <pubDate>Thu, 30 Sep 2021 16:38:59 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/f6adzy/</guid>
      <description>&lt;p&gt;最近，我阅读了一篇名为 &lt;strong&gt;TransRepair: Automatic Testing and Improvement of
Machine Translation&lt;/strong&gt; 的研究论文。该论文介绍了一种名为 TransRepair 的方法，用于
在软件测试领域下自动测试机器翻译模型。下面，我将从几个方面对论文的内容进行总结，
并讨论其中的关键点。&lt;/p&gt;
&lt;h2 id=&#34;transrepair-简介&#34;&gt;TransRepair 简介&lt;/h2&gt;
&lt;p&gt;TransRepair 是一种用于自动检测和修复机器翻译软件一致性问题的方法。它提供了黑盒和
灰盒两种方法来解决机器翻译软件的一致性问题。TransRepair 的主要步骤包括生成测试用
例、创建测试准则和自动修复过程。该方法提供了清晰、严谨和详细的测试用例生成算法，
并采用了四种句子差异的量化方法进行比较。此外，TransRepair 还运用了结构一致性原理
作为断言，并提供了全面的实验设计和多样化的结果。&lt;/p&gt;
&lt;h2 id=&#34;关键问题的理解&#34;&gt;关键问题的理解&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;一致性问题是指机器翻译软件在处理一组具有相似语义和结构但某些特定词语上略有不
同的句子时，在对应翻译句集合中的某一句或几句中的某个或几个部分出现的语义、结
构不一致的现象。&lt;/li&gt;
&lt;li&gt;TransRepair 生成测试用例的方法是对输入的原句进行词语替换，形成突变句组。为了
实现这一操作，TransRepair 使用了词向量模型来计算词语之间的关联性。在选择候选
词后，还会将其带入句子中进行成分分析，以确定句子的语义和语法是否发生较大变
化。&lt;/li&gt;
&lt;li&gt;在验证测试用例输出句子对的一致性时，TransRepair 首先使用 Widiff 进行字符串成
分的差异性比较分析。为了增强相似度量化的可靠性，TransRepair 还构造了原句和翻
译句中涉及的差异成分的部分删除集合，并计算集合中每个元素之间的相似度，选择最
大相似值。论文中使用了四种不同的方法来量化相似度，其中部分方法与之前提到的
SIT 方法有相似之处。&lt;/li&gt;
&lt;li&gt;论文中的实验设计具有独特的特点。它首先提出问题并对解决方法进行探讨，然后围绕
这四个问题设计实验并提供适当形式的实验数据。实验从多个角度论证了该方法的有效
性，包括准确度、有效性、修复能力以及与人工方式的对比等。实验数据的呈现直观易
懂。&lt;/li&gt;
&lt;li&gt;TransRepair 在处理阈值上与 SIT 方法不同。它通过机器小步遍历运算来获得统计上
最优的阈值，并采用人工辅助和统计学分析的方式进行一致性判别，其阈值设定逻辑更
具说服力。而 SIT 方法的阈值设定大多依靠经验，说服力和可操作性较低。&lt;/li&gt;
&lt;li&gt;在 TransRepair 中，自动修复可以分为黑盒和灰盒两种方式。黑盒对应于 Google
Translate，由于该软件未开源，对于输入输出的相关参数了解有限，因此只能对输入
和输出本身进行操作。灰盒对应于 Transformer，它的源码和训练集可获取，因此可以
对其输出结果的可能性进行把握，并在训练集和模型结构上进行修复操作。&lt;/li&gt;
&lt;li&gt;TransRepair 的优势在于对一致性问题的自动检测和修复。该方法具有高准确度、可行
性和可复现性，这与其准确的实施方法以及对现有方法缺陷的考虑和补充密切相关。然
而，该方法的效率较低，有效性仅限于一致性问题。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;总体而言，论文 &lt;strong&gt;TransRepair&lt;/strong&gt; 介绍了 TransRepair 方法作为一种有效的自动测试和改
进机器翻译软件的方法，特别解决了一致性问题。论文详细解释了该方法，并提供了实验证
据和比较分析。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Structure-Invariant Testing for Machine Translation (SIT) 论文阅读总结</title>
      <link>https://blog.bktus.com/archives/e6oo4m/</link>
      <pubDate>Thu, 30 Sep 2021 16:36:04 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/e6oo4m/</guid>
      <description>&lt;p&gt;我之前阅读了 Structure-Invariant Testing for Machine Translation 这篇论文，它提
出了一种关于机器翻译软件系统鲁棒性问题的检测方法。下面我将从几个方面详细介绍我对
其中内容的理解。&lt;/p&gt;
&lt;h2 id=&#34;主要内容&#34;&gt;主要内容&lt;/h2&gt;
&lt;p&gt;SIT 是关于机器翻译软件系统鲁棒性问题的检测方法。这种方法利用了一个蜕变测试中的蜕
变关系，即&amp;quot;结构不变性&amp;quot;。通过选择原始句子、生成相似句子、从翻译软件获取结果、进行
成分解析并量化句子差异、根据设定的阈值筛选并发现问题，SIT 可以高效地检测出机器翻
译软件系统的鲁棒性问题。根据实验结果，SIT 在 19 秒内可以处理 2k+句子，并且对于
Google/Bing Translate 的准确度达到了 70%。然而，仍有提升的空间，可能是由于阈值选
择的原因。&lt;/p&gt;
&lt;h2 id=&#34;对几个关键问题的理解&#34;&gt;对几个关键问题的理解&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;为什么机器翻译软件存在鲁棒性问题？ 机器翻译软件系统的核心模块通常采用深度学
习方法或技术。深度学习模型中每层的维度较高，导致训练模型在向量空间中对不同标
签区域的界定可能模糊不清。当输入值接近边界时，稍微做出微小改变可能导致模型输
出剧烈变化。&lt;/li&gt;
&lt;li&gt;什么是结构不变性？ 结构不变性是指经过对某种语言的句子进行一些特定且微小的词
单位修改后，其语义和语法上的结构在转换为对应翻译后通常保持不变。结构不变性是
研究机器翻译软件系统相关问题的经验和统计学意义上的一个切入点。&lt;/li&gt;
&lt;li&gt;为什么要引入结构不变性？ 引入结构不变性是为了进行蜕变测试，以探索机器翻译软
件系统的鲁棒性问题。引入结构不变性的目的有两个：一是由于自然语言关系和变化复
杂多样，难以得到一种通用的测试定理作为基准进行测试，因此通过控制变量，得到类
似于经验或统计意义上正确的起点，展开测试研究；二是自然语言相关测试的测试用例
难以人工构建，引入结构不变性可以方便地利用现有少量样本生成大量测试用例。&lt;/li&gt;
&lt;li&gt;如何利用结构不变性生成语义与语法相似的语句？ 在 SIT 中，使用了 BERT 模型来生
成语义与语法相似的语句。SIT 依赖于 BERT 的大型语料训练以及遮罩和双向反馈学习
等技术，以抑制词语替换后整个句子的语义改变或不符合语法和使用习惯等问题。SIT
通过在 BERT 之后增加一个轻量级的分类器来辅助生成预备替换词语的候选列表。&lt;/li&gt;
&lt;li&gt;如何量化句子的差异以判断机器翻译软件系统是否存在鲁棒性问题？ SIT 使用了三种
方法来量化句子差异：字符串差异分析、成分解析树分析和依存解析树分析。SIT 直接
对翻译软件的输出结果进行以上三种分析，并对它们的效果进行比较。然而，这三种句
子差异分析方法都有一定的局限性，可以在进一步的工作中探索综合使用这三种方法进
行判定的方式。&lt;/li&gt;
&lt;li&gt;SIT 具有哪些优势？有哪些不足？ 在论文中，作者讨论了 SIT 的优势和不足。总的来
说，SIT 的优势在于其能够检测多种类型错误（未翻译、过度翻译、错误调整、逻辑不
清）。然而，我认为其测试用例的生成方式、错误量化和检测方法相对粗糙，导致实验
下准确性并不高。修复和阈值设定需要人工参与，这也是其另一个不足之处。&lt;/li&gt;
&lt;li&gt;SIT 可以有哪些应用？ SIT 主要应用于对运用了 AI 模型的机器翻译软件系统进行鲁
棒性测试。通过 SIT 的自动检测和人工修复训练样本，机器翻译软件的鲁棒性可以得
到提升。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;SIT 是一种检测机器翻译软件系统鲁棒性问题的方法。通过选择原始句子、生成相似句子、
获取翻译结果、进行成分解析和量化句子差异，SIT 可以高效地检测机器翻译软件系统的鲁
棒性问题。实验结果显示，SIT 可以在 19 秒内处理 2k+句子，并且对于 Google/Bing
Translate 的准确度达到了 70%。然而，仍有改进的空间，可能是由于阈值选择的原
因。SIT 利用 BERT 模型生成语义和语法相似的语句，并使用三种方法来量化句子差异。总
体而言，SIT 的优势在于能够检测多种类型的错误，但其测试用例生成方式和检测方法仍有
改进空间。SIT 主要应用于对应用 AI 模型的机器翻译软件系统进行鲁棒性测试，并通过自
动检测和人工修复训练样本来提升鲁棒性。&lt;/p&gt;</description>
    </item>
    <item>
      <title>掌握C&#43;&#43;右值引用的十大要点：如何正确处理纯右值和将亡值</title>
      <link>https://blog.bktus.com/archives/u2cy96/</link>
      <pubDate>Thu, 30 Sep 2021 16:19:20 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/u2cy96/</guid>
      <description>&lt;p&gt;最近由于工作需要，我阅读了很多关于 C++右值方面的材料。在 C++中，右值是一个非常重
要的概念，它对于理解 C++的内部机制和实现高效代码至关重要。本文将总结了 10 个关于
右值的实践经验。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;C++右值有两种：纯右值、将亡值。右值引用可以延长将亡值的生命周期，使得将亡值
能够被正常使用，而不会被错误地释放。&lt;/li&gt;
&lt;li&gt;右值引用的一个作用是延长右值的生命周期。右值引用可以延长将亡值的生命周期，使
得将亡值能够被正常使用，而不会被错误地释放。&lt;/li&gt;
&lt;li&gt;临时对象作为右值处理。这种对象往往会在一些表达式中自动创建，然后被立即使用。
使用右值引用来绑定临时对象，可以让程序更高效地处理这些对象，避免了不必要的内
存拷贝操作。&lt;/li&gt;
&lt;li&gt;移动构造函数尽可绑定右值非常量。这是因为右值非常量可以被修改，而右值常量则不
能。移动构造函数会破坏源对象，所以只有右值非常量才能被移动构造函数绑定。&lt;/li&gt;
&lt;li&gt;对于一个右值对象，允许调用成员函数。这与左值对象类似。但需要注意的是，对于一
个将亡值，如果其生命周期结束，那么调用其成员函数可能会导致程序出现未定义行
为。&lt;/li&gt;
&lt;li&gt;右值可以被修改（这也说明了其可以被破坏）。因此，在使用右值时需要谨慎处理，以
避免因为修改了右值而导致程序出现问题。&lt;/li&gt;
&lt;li&gt;右值不能当作左值使用，左值可以当作右值使用。这是因为左值具有实际地址，并且与
右值有同样地表现。&lt;/li&gt;
&lt;li&gt;常量左值引用可以绑定到右值。这种引用可以避免将右值对象修改的风险，同时还可以
延长右值的生命周期，使其能够被正常使用。&lt;/li&gt;
&lt;li&gt;返回右值引用的函数在几乎所有情况下是糟糕的。因为返回右值引用往往会导致右值的
生命周期延长，从而使其可能被错误地使用。对于返回右值的函数，建议使用值返回的
方式。&lt;/li&gt;
&lt;li&gt;在大部分情况下 return 中使用是 std::move 并不会将事情变得更好，相反该操作会
阻止编译器进行返回值优化。&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>探究计算机中断处理：了解Intel x86处理器下的外部中断、异常和陷入</title>
      <link>https://blog.bktus.com/archives/eicrzq/</link>
      <pubDate>Thu, 30 Sep 2021 16:05:53 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/eicrzq/</guid>
      <description>&lt;p&gt;处理器中断处理是计算机体系架构中必须掌握的知识之一。在 Intel 的 x86 处理器下，中
断可以分为外部中断、异常和陷入。外部中断来自硬件，是随机发生的，而异常则是处理器
内部执行指令过程中检测到错误条件的结果。陷入则是由程序产生的，通常是由 INT
n、INTO 等指令触发的。&lt;/p&gt;
&lt;p&gt;在 x86 处理器中，中断处理程序负责处理中断，异常处理程序负责处理异常，而系统调用
服务程序则负责处理陷入。这些处理程序可以位于内存空间的任何位置，并且可以有不同的
特权级。&lt;/p&gt;
&lt;p&gt;Intel 处理器使用中断门、陷阱门和任务门来定义处理程序的入口地址。其中，中断门和陷
阱门是进入异常处理程序的门户。选择符和偏移量合起来定义了一个处理程序的入口地址。
中断门进入处理程序时 IF 标志被清掉，而陷阱门进入处理程序时 IF 标志保持不变。&lt;/p&gt;
&lt;p&gt;Intel 处理器为每个中断和异常定义了一个中断向量号，并通过中断描述符表（IDT）建立
中断向量号和门之间的对应关系。IDT 可以驻留在线性地址空间的任何位置。Intel 处理器
专门提供了一个 IDTR 寄存器来记录 IDT 的基地址和界限信息。&lt;/p&gt;
&lt;p&gt;Intel 处理器定义了 256 个中断向量号，其中 0~31 被处理器保留。 处理器中的异常可以
分为故障类异常和终止类异常。故障类异常可以被更正，而终止类异常则是无法被处理器自
行解决的严重错误。为了保证安全性，通过中断门或陷阱门只能向同级或更高特权级的代码
段转移控制。通常情况下，处理程序定义在内核代码段中（0 特权级代码段）。 在中断发
生时，处理器会自动在栈顶压入一些参数，其中 EFLAGS 是中断或异常发生前的系统状
态，SS:ESP 是中断或者异常发生前用户堆栈的栈顶，CS:EIP 是中断或者异常的返回地址。&lt;/p&gt;
&lt;p&gt;64 位模式中，处理程序必须在 64 位代码段中，因而中断和陷阱门描述符被扩充到了 16
字节，其中偏移量被扩充到了 64 位；IDT 找那个仅有新格式的门描述符；堆栈宽度变成了
64 位，而且当中断发生时，会无条件地压入栈指针（SS:RSP）当需要切换堆栈时 SS 被强
制设置为 NULL；新增了中断堆栈表（IST）机制，允许特定的中断或者异常指定专门的堆
栈。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Intel x86处理器内存保护 概要知识点</title>
      <link>https://blog.bktus.com/archives/71tr8x/</link>
      <pubDate>Thu, 30 Sep 2021 16:05:31 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/71tr8x/</guid>
      <description>&lt;p&gt;一旦处理器内存保护机制被启动，处理器就会对每一次内存访问进行保护性检查，以确保所
有的访问都满足保护策略。保护检查和地址转换是并行进行的。&lt;/p&gt;
&lt;p&gt;保护检查包含段级检查和页级检查。检查顺序是先段后页，检查依据是段描述符，页目录和
页表，检查的基础是特权级。&lt;/p&gt;
&lt;p&gt;特权级是 Intel 为实现保护而定义的特权编号。&lt;/p&gt;
&lt;p&gt;段一级的检查包括段界限检查，段类型检查，特权级检查，长指针检查等。段一级检查的原
则是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;低特权级的代码不能访问高特权级的数据&lt;/li&gt;
&lt;li&gt;高特权级的代码可以访问低特权级的数据&lt;/li&gt;
&lt;li&gt;代码只能使用与其特权级相同的堆栈，当特权级切换时，堆栈也要随之切换。&lt;/li&gt;
&lt;li&gt;只能向具有相同特权级的非相容代码段转移控制（长 JMP 和长 CALL）&lt;/li&gt;
&lt;li&gt;可以向同等或者较高特权级的相容代码段转移控制，但不能向低特权级的相容代码段转
移控制（长 JMP 和长 CALL）。&lt;/li&gt;
&lt;li&gt;即使调用门、中断门、陷阱门，也不能从高特权级向低特权级转移控制。&lt;/li&gt;
&lt;li&gt;不允许使用长 RET 向高特权级转移控制。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;页一级的检查包括特权级检查和读写检查。相关标志是页目录/页表项中的 U/S 和 R/W
位。U/S 位 0 的页是超级页，为 1 是代表用户页。一般情况下，超级页中的代码可以访问
所有页（不管 R/W 标志），用户页中的代码只能访问用户页。当 CR0.WP 被设置为 1 时，
超级页中的代码也不能写只读用户页。&lt;/p&gt;
&lt;p&gt;NXB 为 1 的页只能用作数据页，试图执行数据页的指令会引起处理器异常。&lt;/p&gt;</description>
    </item>
    <item>
      <title>intel 64 体系常见内存管理方式</title>
      <link>https://blog.bktus.com/archives/l5g4e0/</link>
      <pubDate>Thu, 30 Sep 2021 16:05:14 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/l5g4e0/</guid>
      <description>&lt;p&gt;内存管理是操作系统中非常重要的一个部分。随着计算机技术的不断发展，内存管理的方式
也在不断演变。本文将介绍 intel 64 体系几种常见的内存管理方式。&lt;/p&gt;
&lt;p&gt;平板式内存管理是一种比较简单的内存管理方式。它采用页式管理，屏蔽掉段式管理。具体
来说，它将逻辑地址直接映射为线性地址，定义一个代码段和一个数据段，两个段的大小都
是 4GB。这种方式的好处是简单易懂，但是它的缺点是不能进行多进程的内存隔离。&lt;/p&gt;
&lt;p&gt;为了解决多进程内存隔离的问题，可以采用保护平板式内存管理的方式。具体来说，它定义
了内核代码段、内核数据段、用户代码段和用户数据段，每个段的基地址都是 0，大小为
4GB。进程执行内核代码时使用内核段，执行用户代码时使用用户段。这种方式的好处是可
以进行多进程的内存隔离，但是它的缺点是需要进行地址转化，影响效率。多段式内存管理
是一种完全采用段式管理的方式，屏蔽掉页式管理。它可以进行多进程的内存隔离，但是需
要进行地址转化，也会影响效率。&lt;/p&gt;
&lt;p&gt;基于物理地址拓展的页式内存管理是一种支持更大物理地址空间的方式。它引入了物理地址
拓展（PAE）机制以支持 36 位物理地址。该管理模式中，物理地址空间被扩充到了 64GB，
但线性地址空间仍然为 4GB。页目录和页表项被扩充到了 64 位，因而一个页目录或者页表
中的项数变成了 512，一个页目录仅能描述 1GB 线性地址空间。所以引入了一个只有四个
表项的页目录指针表（PDP）。CR3 指向 PDP。地址转换机制被修改。当页目录项中的 PS
位被设置为 1 时，它描述的页变成了 2MB 页。&lt;/p&gt;
&lt;p&gt;在 64 位模式中，段通常被关闭，不再做段界限检查。CS，DS，ES，SS 的基地址处理器统
统看作 0。但 FS 和 GS 可以不是 0，将逻辑地址转换为先行地址的时候要加上 FS 或者
GS 的基地址。FS 和 GS 的基地址位 64 位地址，兼容模式中只使用它的低 32 位，记录在
MSR 中。在 64 位模式中，对于内存的管理完全依靠分页机制。&lt;/p&gt;
&lt;p&gt;Intel64 体系结构扩展了 PAE 机制，使之能够支持 64 位线性地址和 52 位物理地址。拓
展包括：&lt;/p&gt;</description>
    </item>
    <item>
      <title>段页式内存管理概要</title>
      <link>https://blog.bktus.com/archives/neyb3m/</link>
      <pubDate>Thu, 30 Sep 2021 16:04:50 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/neyb3m/</guid>
      <description>&lt;p&gt;段页式内存管理中，段的线性地址被分割成大小相等的线性页（4KB，4MB 或者 2MB 等）。
物理内存空间同样也被分成相同大小的物理页。操作系统维护一个页表，用于管理线性页到
物理页的映射。页表在 IA-32 体系结构中分为两级，即页目录和页表&lt;/p&gt;
&lt;p&gt;页目录是一个数组，其元素叫做页目录项（PDE），每个页目录项描述一个页表。页目录的
大小为一页（4KB），一个页目录中有 1024 个页目录项。页目录项的大小为 4 字节。页表
大小为一页（4KB）。页表项的大小为 4 字节，所以一个页表最多可以描述 1024 个线性
页。&lt;/p&gt;
&lt;p&gt;物理页是预先划分好的，其开始位置一定在 4KB（2^12）的边界上。所以低 12 位全部是
零。然后低 12 位就可以储存而外的信息。&lt;/p&gt;
&lt;p&gt;P 是存在位。R/W 是读写标志位。U/S 是用户标志位，0 表示超级用户。A 是存取标志
位。D 是脏标志位。&lt;/p&gt;
&lt;p&gt;在页目录项中 PAT 标志换成了 PS 标志，表示物理页尺寸。&lt;/p&gt;
&lt;p&gt;CR3 寄存器专门存放当前使用的页目录的物理地址，因此 CR3 又叫做页目录基地址寄存
器。只要进程在活动，它的页目录就应该一直驻留在内存。&lt;/p&gt;
&lt;p&gt;页目录项也可以直接指向物理页，加快地址转换速度，通常将操作系统内核所占用的页设置
为 4MB 页。该页目录项的 PS 地址为 1 事，它所描述的是一个 4MB 的页而不再是一个页
表。&lt;/p&gt;
&lt;p&gt;页式管理机制是操作系统内核启动的，启动方法是将 CR0 中的 PG 标志设置为 1。&lt;/p&gt;
&lt;p&gt;启动分页机制后，每个线性地址都需要经过页目录和页表的转换。IA-32 体系结构加入了一
个高速缓存 TIB，其中储存最近使用的页目录和页表项。TIB 的经常的刷新工作由操作系统
内核负责。当页目录和页表项改变时，内核必须使得 TIB 相应的项失效。当 CR3 改变
时，TIB 中的所有内容（Global 页除外）会自动失效。INVLPG 指令可以将 TLB 中的指定
项设置为无效。&lt;/p&gt;</description>
    </item>
    <item>
      <title>段内存管理概要</title>
      <link>https://blog.bktus.com/archives/9fsajz/</link>
      <pubDate>Thu, 30 Sep 2021 16:04:34 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/9fsajz/</guid>
      <description>&lt;p&gt;IA-32 体系中提供了段页式内存管理机制，先分段再分页。提供页式是为了支持虚拟内存。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;段：处理器的可寻址的线性内存空间被划分成了若干个大小不同的段。一个段是线性地址
空间中的一个连续的区间。段中可保存代码、数据、堆栈或者其他数据结构。段的属性信
息由与之对应的段描述符描述。段描述符是一个数据结构。Intel 用段描述符表来管理。
段描述符表最大可达 64KB。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;当 G 为 0 时，段以字节为单位，最大的段长为 1MB。当 G 为 1 时，段以页（4kb）
为单位。最大的段长为 4GB。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DPL 是段的特权级，其值在 0~3 之间。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;S 是系统标志，用于区分段的类别。0 表示系统段，1 表示用户段。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Type 是段的类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;对于系统段。类型域由 4 位组成，可表示 16 个系统段类型之一。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于用户段。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第三位为 0 表示数据段，此时第二位表示地址的拓展方向（0 表示大扩展方
向），第一位表示段是否可写。&lt;/li&gt;
&lt;li&gt;第三位为 1 表示代码段，此时第二位是相容标志（0 表示非相容）。第一位是可
读位。&lt;/li&gt;
&lt;li&gt;第 0 位是存取位。0 表示段尚未存取过。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;D/B 标志表示有效地址和操作数长度。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L 标志仅出现在 IA-32e 模式的代码段中。1 表示 64 位模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;堆栈段通常是向下扩展的、可读写的数据段。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;段描述符表：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全局描述符表（GDT）。在系统进入保护模式前必须为其定义一个 GDT。IA-32 体系结
构专门定义了一个 GDTR 寄存器来存放当前的 GDT 的信息。&lt;/li&gt;
&lt;li&gt;局部描述符表（LDT）是系统段，其中可以存放局部描述符，如进程自己的代码段，数
据段等。IA-32 体系专门提供了一个 LDTR 寄存器，用于保存当前使用的 LDT 信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以用段描述符在段描述符表中的索引来标识它，标识称作段选择符。段选择符是 16 位标
识符。第二位是指示器（TI）表示索引所对的描述符表（0 表示 GDT）。第 3-15 位示索
引，标定位置。第 0、1 位是请求特权级 RPL。一个段选择符加上一个偏移量可以唯一地标
识一个逻辑地址。逻辑地址是程序使用的地址，不是线性地址，也不是物理地址。&lt;/p&gt;</description>
    </item>
    <item>
      <title>了解计算机系统内部运作：内存、I/O设备、总线和外存是如何协同工作的？</title>
      <link>https://blog.bktus.com/archives/kk9cvb/</link>
      <pubDate>Thu, 30 Sep 2021 16:04:19 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/kk9cvb/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;内存是处理器可以直接访问的储存空间。为了加快内存访问速度，计算机系统中通常提供
了一些高速缓存（Cache），高速缓存通常由硬件管理。&lt;/li&gt;
&lt;li&gt;I/O 设备由 I/O 控制器和物理设备组成，处理器通过 I/O 控制器管理物理设备。I/O 控
制器主要由控制与状态寄存器（CSR）和数据寄存器组成。处理器通过读 CSR 来获得设备
状态，通过写 CSR 来控制设备动作，通过读写数据寄存器来交换数据。内核通常将 I/O
设备抽象成一组寄存器，并给一个寄存器一个 I/O 地址。处理器通过 I/O 地址访问 I/O
寄存器。&lt;/li&gt;
&lt;li&gt;现代计算机系统中许多设备寄存器可以被映射到物理地址空间中。此时，每个设备寄存器
都有一个物理内存地址。这种方式的 I/O 称为内存映射 I/O。使用方便但是会消耗物理
内存地址。&lt;/li&gt;
&lt;li&gt;通常把外存抽象成一个数据块的数组，每个数据块都有一个序号处理器可以通过序号随机
读、写外存中的任何一个数据块。对于外存的操作通常以块为单位，因此又称外存为块设
备。对应地，其他 I/O 设备称为字符设备。简而言之，块设备以块为单位进行数据的读
写操作，如硬盘、闪存等；字符设备以字符为单位进行数据的读写操作，如键盘、鼠标、
打印机等。&lt;/li&gt;
&lt;li&gt;总线负责将处理器，内存，I/O 控制器连接起来。常用的总线有
ISA、PCI、PCI-E、AGP、ATA、SCSI 等。总线还负责检测，枚举接在其上的设备。&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>IA-32体系概要</title>
      <link>https://blog.bktus.com/archives/lf80ly/</link>
      <pubDate>Thu, 30 Sep 2021 16:03:49 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/lf80ly/</guid>
      <description>&lt;p&gt;IA-32 体系结构中由三种模式和一种准操作结构：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;实模式：与 8086 兼容的操作模式，有一些拓展。&lt;/li&gt;
&lt;li&gt;保护模式：处理器的一种最基本的操作模式，在这种模式中，处理器的所有指令及体系结
构中的所有特色都是可用的，并且能够达到最高性能。&lt;/li&gt;
&lt;li&gt;系统管理模式，提供给操作系统的一种透明的管理机制，用于实现电源管理等特殊操作。&lt;/li&gt;
&lt;li&gt;虚拟 8086 模式是一个准操作模式，允许处理器在保护模式中执行实模式的程序。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Intel 64 体系结构新增一种 IA-32e 操作模式包含两个子模式&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;兼容模式，在该模式下可以不加修改地运行大多数 IA-32 体系结构的程序&lt;/li&gt;
&lt;li&gt;64 位模式，可以使用 64 位线性地址空间和一些新增加的特性。IA-32e 不再支持虚拟
8086 模式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;处理器加电或者 Reset 后默认操作模式是实模式。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;实模式和保护模式之间的转换由控制寄存器 CR0 中的 PE 位控制。&lt;/li&gt;
&lt;li&gt;保护模式和 IA-32e 模式之间的转换由 IA32_EFER 寄存器中的 LME 和 CR0 中的 PE 位
控制。&lt;/li&gt;
&lt;li&gt;兼容模式和 64 位模式之间的转换由代码段寄存器 CS 和 L 位控制。&lt;/li&gt;
&lt;li&gt;保护模式和虚拟 8086 模式之间的转换由标志寄存器 EFLAGS 中的 VM 位控制。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;进入系统管理模式的唯一途径是 SMI 中断，在系统管理模式中执行指令 RSM 会将处理器切
换回原来的操作模式。&lt;/p&gt;</description>
    </item>
    <item>
      <title>中华传统文化能否带领封建制度中的中华民族走向近代</title>
      <link>https://blog.bktus.com/archives/m1pjw6/</link>
      <pubDate>Thu, 30 Sep 2021 16:00:52 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/m1pjw6/</guid>
      <description>&lt;p&gt;明清时期，是中国古代的封建社会的晚期。这是封建专制主义中央集权制度的强化的时期，
也是中国的封建皇权走向巅峰的时期。另一方面，这也是中华民族逐渐落后与历史潮流的时
期。理学的出现与统治阶级对于理学的强化，逐渐束缚了我们民族的人格与思想。&lt;/p&gt;
&lt;p&gt;为什么中华民族会进入这样一段历史时期。其实这并不是这些皇帝个人的意志的体现，而是
传统文化影响下中华民族的性格与历史大环境所造就的。当中国封建制度走到宋代的时候，
相对于前代唐代，能很明显地感觉到文化与制度双重影响下的人格的束缚越来越强。我认
为，出现这种情况的正显现了封建制度已经越来越不能适应于生产力与思想发展后人们自然
产生的对于新兴的生产关系，人格自由的需求。这类新兴事物，在明王朝对于社会的思想控
制统治相对薄弱的中后期可以窥见，在这个时期涌现了一大批思想家，像李贽、黄宗羲。李
贽将矛头直指封建礼教和整个正统思想，在一定程度反映了基本主义萌芽时代的要求。黄宗
羲，他主张的“天下为主，君为客”之说，反映了由生产力发展所导致的传统社会生产关系的
变化。具有反专制主义的特征。&lt;/p&gt;
&lt;p&gt;面对新兴的事物，传统封建统治阶级同他们所设计的集权化的封建制度感到眼花缭乱。在落
后的世界观与对于落后生产关系的理解的影响下，他们对接受、利用与管理这些新兴事物显
得力不从心。草率地将这些新兴事物纳入他们熟悉的统治体系是不可能做到的，他们的统治
体系与他们的思想本身并没有这些基因。他们对这种令他们感到纷乱的事物产生了本能的恐
惧，所以他们要清除这些让他们感到烦心的事物，让社会与人们的思想重新回到他们认为的
样子中去。只有这样这样人民的一举一动才能在他们的掌握之中，他们才能在既定框架下更
有效地实现他们的统治。&lt;/p&gt;
&lt;p&gt;于是到了明代，底层农民出身的朱元璋对于元末的混乱有深刻的体会。在中国传统文化影响
下，他的不可避免地渴望社会的秩序与道德的重建，建立一个秩序的王朝。但是，在他的那
个时期，新兴事物与思想的出现让社会变得复杂，社会本身已经不可能恢复到秦汉与隋唐时
期。这让他本能地走向了对于人民更严格的控制。兴八股，造户籍，明律法，这是他采取的
措施。以孝治天下的主张，更是希望国家臣民能够在伦理道德的强力约束下接受统治。选拔
国家人才的科举制度，也成为了知识分子思想上的一道重重的枷锁。对于这些知识分子出身
的官员，他们的思想举动被牢牢锁定在私塾五经的范畴。丞相的废除与锦衣卫，东厂的设
立，更加体现了中央皇权的加强，中央皇权对于社会的控制更加牢固。于是在明初这种恐怖
环境下，新兴事物根本无力与已经占据绝对优势的全副武装的封建秩序对抗。需要注意，古
代中国的律法，一直被人民视为对于臣民严重违反社会道德规范的严厉惩罚与对于臣民行为
的在道德以外的严格规定，并不是现代意义上保护人民权利的法律。&lt;/p&gt;
&lt;p&gt;在思想方面，中华传统的文化本身具有它的“趋同”的特征，在这种环境下新兴事物的传播本
来就缓慢。随着传统的儒家文化的逐渐地封建化与经文化，在人们的思想中面对这些新兴的
东西时是麻木的，不理解的。对于接受这些新兴思想的少数人，一直被排除在主流社会之
中，不仅受到道德与封建法律的联合打压，而且受到主流思想的排挤与污蔑，更受到在封建
世界观影响下成长起来的自己对于自己思想的怀疑。再者，古代中国人对于“天下”，“朝
廷”，“君父”的根生蒂固的认识下，在王朝更替，集权封建制度控制相对较弱的时期，仍然
会自然地选择走向另一个新的集权封建制度的统治。&lt;/p&gt;
&lt;p&gt;从制度与文化两方面看，如果不受到外力，在相当长的历史时期，中华民族会生活在在这种
集权封建体制与封建化的文化中。在这段时期，新兴事物的传播是及其缓慢的。而恰恰是这
些新兴制度，很自然的代表了人类社会发展的根本方向。但不能否认，随着生产力的继续发
展，新兴的生产关系与相对应产生的思想绝不会被扑灭扼杀。相反，在不断积累中，它的力
量会越来越强大，直到在未来某个历史时期，它将取代传统的封建生产关系。&lt;/p&gt;</description>
    </item>
    <item>
      <title>中华传统文化与民族近代命运的关系</title>
      <link>https://blog.bktus.com/archives/2pqkja/</link>
      <pubDate>Thu, 30 Sep 2021 16:00:26 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/2pqkja/</guid>
      <description>&lt;p&gt;在讨论传统文化之前，先来讨论民族。先来看看民族的概念：民族是指经长期历史发展而形
成的稳定共同体，一群基于历史、文化、语言与其它人群有所区别的群体。根据定义可以知
道历史、文化、语言是区本民族别于其他民族的重要的三个元素。而这三个元素并不是相互
独立的，相反，它们是相互影响，相互交融的，谁也离不开谁。&lt;/p&gt;
&lt;p&gt;从文化来看，一个民族的文化渗入它的历史之中，影响着本民族个体乃至全体的思维，进而
影响在特定历史条件下本民族面对历史提出的问题所作出的决定。类似地，文化渗入语言，
一个民族的语言的文法，词汇，表达中都有明显的文化痕迹。所以，文化极大地塑造了一个
民族的性格，赋予一个民族它的灵魂，是一个民族区别于其他民族的极为重要的因素。中华
传统文化之于中华民族来说亦是如此。&lt;/p&gt;
&lt;p&gt;但是近代以来，中华传统文化在中国人心中逐渐地淡化，甚至于个别个体全然忘却。近来频
繁地出现了种种违反道德的社会事件，从表面看仅仅是违反道德而已。但是深究其根本，则
是社会道德的母体传统文化本身，被本民族个别个体所轻视，淡忘所导致的道德约束力的下
降。本民族的传统文化在民族个体在内心不被认同，将导致中华民族的凝聚力与认同感的下
降，对于中华民族来说将是灾难性的。就像当下，面对日美文化，中国青年热衷接受；面对
传统文化，中国青年则一脸茫然。但这又是为什么？中华传统文化到底是什么？未来将何去
何从？&lt;/p&gt;
&lt;p&gt;在近现代中国人的理解中，传统文化似乎制约了社会的发展。诚然，传统文化中三常五纲，
逆来顺受，宗法等级确实在一个现代人看来是落后的。并且传统文化中缺乏对于论断的进行
思维论证的态度也是不可取的。既然对于传统文化产生了这样的疑问。那么在封建时期，传
统文化的状态就是我们应当首先讨论的问题。&lt;/p&gt;
&lt;p&gt;中华传统文化在近代为什么不符合社会的发展潮流，是因为传统文化本身被很大程度地封建
化。明清时期，是中国古代的封建社会的晚期。这是封建专制主义中央集权制度的强化的时
期，也是中国的封建皇权走向巅峰的时期。理学的出现与统治阶级对于理学的强化，逐渐束
缚了我们民族的人格与思想。在封建专制主义制度的强力作用下，传统文化很大程度上向着
适应封建统治的方向上发展。为什么中华民族会进入这样一段历史时期。其实这并不是这些
皇帝个人的意志的体现，而是传统文化影响下中华民族的性格与历史大环境所造就的。 其
实，当中国封建制度走到宋代的时候，相对于前代唐代，能很明显地感觉到文化与制度双重
影响下的人格的束缚越来越强。&lt;/p&gt;
&lt;p&gt;我认为，出现这种情况的正显现了封建制度已经越来越不能适应于生产力与思想发展后人们
自然产生的对于新兴的生产关系，人格自由的需求。面对新兴的事物，传统封建统治阶级在
落后的世界观与对于落后生产关系的理解的影响下，对接受、利用与管理这些新兴事物显得
力不从心。草率地将这些新兴事物纳入他们熟悉的统治体系是不可能做到的，他们的统治体
系与他们的思想本身并没有这些基因。他们对这种令他们感到纷乱的事物产生了本能的恐
惧，努力让社会与人们的思想重新回到他们认为的样子中去。&lt;/p&gt;
&lt;p&gt;于是到了明代，底层农民出身的朱元璋封建文化与历史的巨大惯性的影响下，不可避免地渴
望社会的秩序与道德的重建，建立一个统一的君主专制的封建的王朝。但是，在他的那个时
期，新兴事物与思想的出现让社会变得复杂，社会本身已经不可能恢复到秦汉与隋唐时期。
这让他本能地走向了对于人民更严格的控制。兴八股，造户籍，明律法，这是他采取的措
施。纯粹的以孝治天下的主张，更是希望国家臣民能够在伦理道德的强力约束下接受统治。
选拔国家人才的科举制度，也成为了知识分子思想上的一道重重的枷锁。对于这些知识分子
出身的官员，他们的思想举动被牢牢锁定在私塾五经的范畴。丞相的废除与锦衣卫，东厂的
设立，更加体现了中央皇权的加强，中央皇权对于社会的控制更加牢固。于是在明初这种恐
怖环境下，新兴事物根本无力与已经占据绝对优势的全副武装的封建秩序对抗。&lt;/p&gt;
&lt;p&gt;需要注意，古代中国的律法，一直被人民视为对于臣民严重违反社会道德规范的严厉惩罚与
对于臣民行为的在道德以外的严格规定，并不是现代意义上保护人民权利的法律。 在思想
方面，封建化的中华传统的文化逐渐强化了它的“趋同”的特征，在这种环境下新兴事物的传
播本来就缓慢。随着传统的儒家文化的逐渐地封建化与经文化，对于接受这些新兴思想的少
数人，一直被排除在主流社会之中，不仅受到道德与封建法律的联合打压，更受到在封建世
界观影响下成长起来的自己对于自己思想的怀疑。再者，古代中国人对于“天下”，“朝
廷”，“君父”的根生蒂固的认识下，在王朝更替，集权封建制度控制相对较弱的时期，仍然
会自然地选择走向另一个新的集权封建制度的统治。 所以，在被封建地主阶级改造的儒家
思想的巨大惯性下运转中国，两千年的对中华民族的思想的改造与对于儒家文化的单方面阐
释下，使得以儒家思想为主体的传统文化已经变成他们他们维系统治的有力工具。以儒家思
想为主体的中华传统文化在两千年的封建社会的进程中逐渐向它的“趋同”与“秩序”的方向上
倾斜，越来越不利于生产力与新思想的发展，社会进入了相对稳定的停滞时期。&lt;/p&gt;
&lt;p&gt;在明朝后期到乾隆时期，皇帝对于西方传来的闻之未闻的科学技术始终是抱着玩的态度的原
因也出自于这。在君君臣臣父父子子的不断的强化中，中国的封建制度走到了它的尽头。
既然前面阐释了传统文化并不能将我们中华民族带入近代的原因，那么我们的传统文化与西
方文化的究竟有没有优劣之分？&lt;/p&gt;
&lt;p&gt;西方文化与我们的传统文化绝无优劣之分。西方文化个性化契约化的文化产生有它的历史渊
源。日耳曼首领靠他们的战士为其战斗，但这并不是无偿的。相对地，首领必须定期为战士
们提供他们理应的到的战利品。这是领主应该做的，也是必须做的。这样，首领与战士之间
的关系依靠着这种简单的契约关系维持。在这种关系下，战士的人格本身独立的，而首领无
权直接干涉战士的私人生活。到了中世纪，首领变成了领主，战士变成了封臣，这种习惯仍
然存在。领主分给封臣，封臣也必须履行他们的封建义务。封臣的封臣不是领主的封臣，这
是因为他们在越级之间没有契约关系。农民与封建主的关系大抵如此。在这种社会运作制度
下，个人有相对的独立性。西方的封建制度并不像封建时代的中国一样，形成了相对集中的
中央封建强权。契约观念与罗马法的巨大影响共同作用下产生了西方现代意义上的法律，更
好地保证了人的权利。在中世纪与近代之交的西欧的城市法律下自由的气息更加明显，为新
事物的产生创造了有利的条件，加速了西方的近代化。这是《自由论》的作者密尔所认为有
利于人类社会的发展的趋势。西方比我们提早进入近代，并不是西方的文化就是好的，就该
拿来作为我们的文化。没有相应的历史积累沉淀，生搬硬套注定无法成功，无法与我们的民
族的本性相适应。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Life of a Pixel Chromium浏览器内核渲染原理 学习笔记</title>
      <link>https://blog.bktus.com/archives/oams24/</link>
      <pubDate>Tue, 07 Sep 2021 09:52:26 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/oams24/</guid>
      <description>&lt;p&gt;Chromium 浏览器内核中，来自前端的内容如何在最终转换成为屏幕上的各个像素点，也就
是浏览器内核渲染过程，这是一个复杂的工程上的一系列步骤。对于这些复杂的步骤我们需
要把握的方面包括该过程每个阶段的设计思想、数据模型、数据模型的交互。深入而仔细地
理解上述内容，有利与我们阅读庞大源码中始终保持清醒找准定位。下面我将基于我对
Life of a Pixel 的理解仔细来讨论这个过程。&lt;/p&gt;
&lt;h2 id=&#34;life-of-a-pixel-输入与输出&#34;&gt;Life of a Pixel 输入与输出&lt;/h2&gt;
&lt;p&gt;首先需要谈谈输入与输出，这一系列步骤的输入成为 Web Content。它由一系列现有协议所
定义的一套描述 Web 内容的文本主要组成，当然也包括其他引用内容。现有的协议（我们
常称为编程语言），通常是 HTML、CSS 与 JavaScript。这三者分别有定义了 Web 内容的
结构内容、样式、逻辑。但这并非严格分工，在当下流行的前端设计思想（前后端分离）中
JavaScript 正在承担着越来越多的职责。JavaScript 本身也正在不断地变得独立，近年来
逐渐跳出浏览器这个平台来独立发挥其作用（node.js、react-vr）。 另一方面，谈谈输
出。如何绘制屏幕上的像素，涉及到计算机图形学方面的理论与工程。在传统上，我们可以
认为计算机向屏幕输出内容经历了以下步骤。应用软件将其想要表达的图形内容转换成为对
操作系统与图形相关的函数库的调用（OpenGL、Direct X 等），这些函数库通过操作系统
中安装驱动程序及其他操作系统有关服务向硬件（GPU 等）传送数据与指令，并操纵硬件的
计算核心与存储器（GPU 等）完成光栅化等步骤、最终将硬件（GPU 等）存储器中的最终内
容转化为向屏幕输出的信号。在这方面，由函数库（OpenGL）所提供的 API 都是比较低级
的。 举个例子，原来我也做过 OpenGL 相关的编程，虽然现代 OpenGL 提供一些模型与协
议（如管线等）来简化工作，但是其提供的模型以及依照模型设计的 API 带有明显的硬件
气息。对于 OpenGL 来说，调用者要精确输入预设的或者利用 GPU 程序计算出的数据其所
绘制内容的在几何坐标系下的位置、颜色以及绘制顺序。 由输入输出来大致推断，浏览器
的工作是按照先行前端协议（前端编程语言）及其附属多媒体、数据等方面的内容精确理解
前端开发者对于 Web 页面的描述，并通过数据的层层流动与转换计算推断出图形函数库所
需的各类信息。现行前端协议的复杂性与兼容性与鲁棒性要求使得这一步骤的实现十分复杂
与庞大。而对于性能与稳定的要求更提升了设计与实现上的难度。实现这一系列不仅仅是技
术上，而且也是软件工程上的难题。&lt;/p&gt;
&lt;h2 id=&#34;页面生命周期综述&#34;&gt;页面生命周期综述&lt;/h2&gt;
&lt;p&gt;由上述对于输入与输出的讨论，我们可以理解 Chromium 团队提出以下有关于页面生命周
期。&lt;/p&gt;</description>
    </item>
    <item>
      <title>为MacOS的终端加上代理设置</title>
      <link>https://blog.bktus.com/archives/5ytwua/</link>
      <pubDate>Tue, 25 May 2021 20:15:28 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/5ytwua/</guid>
      <description>&lt;p&gt;MacOS 现在默认采用 Zsh，所以在用户家目录下寻找.zshrc 配置文件，如果没有则自行创
建。 编辑.zshrc 文件，在最后加入下列代码&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;\# set proxy
alias proxy=&amp;#39;export all\_proxy=socks5://127.0.0.1:1234&amp;#39;
alias unproxy=&amp;#39;unset all\_proxy&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;添加完毕后，保存，在终端输入以下命令&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% source ～/.zshrc
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;完毕。 如果需要使用代理，则预先输入 proxy 命令。如果需要取消代理，则输入 unproxy
命令。 或者如果需要默认启用代理的话，在.zshrc 配置文件末尾添加&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% export https\_proxy=http://127.0.0.1:7890 http\_proxy=http://127.0.0.1:7890 all\_proxy=socks5://127.0.0.1:7890
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;保存。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% source ～/.zshrc
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;完毕。&lt;/p&gt;</description>
    </item>
    <item>
      <title>HyperV Ubuntu虚拟机开启增强会话 调整分辨率 启用剪切板</title>
      <link>https://blog.bktus.com/archives/hx2req/</link>
      <pubDate>Tue, 25 May 2021 19:52:23 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/hx2req/</guid>
      <description>&lt;p&gt;在 HyperV 下 Windows 系虚拟机默认就能够开启增强会话。在增强会话下可以方便地和宿
主机共享剪切板与文件，并且在增强会话开启时也能够比较方便地调整分辨率。而 Ubuntu
等 Linux 系统下则默认为基本会话，分辨率的调整需要修改引导文件，而剪切板和宿主机
是独立的非常不方便。 进过查找，找到了一种可以在 Ubuntu 20.04 下开启增强会话的方
法，使用后有效，遂在此记录。 首先需要开启增强会话的话必须先在创建虚拟机的时候开
启第二代虚拟机选项，在首次启动的时候关闭 Secure Boot。记得在安装 Ubuntu 的时候不
要开启自动登录选项。 在终端下输入&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% wget https://raw.githubusercontent.com/Hinara/linux-vm-tools/ubuntu20-04/ubuntu/20.04/install.sh
% sudo chmod +x install.sh
% sudo ./install.sh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在 Windows Power Shell 运行以下命令，然后重启。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;\&amp;gt; Set-VM -VMName &amp;lt;your\_vm\_name&amp;gt;  -EnhancedSessionTransportType HvSocket
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;重启后，就能看到链接虚拟机后会话已经为增强会话模式而后 Ubuntu 进入的 XRDP 登录页
面，此时正常输入用户名密码即可。&lt;/p&gt;</description>
    </item>
    <item>
      <title>解决oh-my-zsh plugin &#39;zsh-autosuggestions&#39; not found 与 plugin &#39;zsh-syntax-highlighting&#39; not found问题</title>
      <link>https://blog.bktus.com/archives/9s3ea1/</link>
      <pubDate>Tue, 25 May 2021 17:49:23 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/9s3ea1/</guid>
      <description>&lt;p&gt;安装 zsh 插件 zsh-autosuggestions 或者 zsh-syntax-highlighting 的时候，我们一般
会遇到 oh-my-zsh plugin &amp;lsquo;xxx&amp;rsquo; not found 的问题。现在，我们分析并解决 oh-my-zsh
plugin &amp;lsquo;zsh-autosuggestions&amp;rsquo; not found 与 plugin &amp;lsquo;zsh-syntax-highlighting&amp;rsquo; not
found 问题。 问题产生的原因是，没有把插件的代码仓库克隆到本地位置上，所以你想要
的插件其实并没有被安装。 解决问题非常简单，只需要简单输入以下命令：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions
$ git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting
$ source ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后，你可以重新打开 shell，可以发现问题已解决。你也可以用该方法解决其他插件的此
类问题。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Synology Drive版本控制功能使用心得</title>
      <link>https://blog.bktus.com/archives/d010i6/</link>
      <pubDate>Wed, 19 May 2021 17:29:43 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/d010i6/</guid>
      <description>&lt;p&gt;经过一段时间对于 Synology Drive 的版本控制功能的使用，总结出以下不建议使用版本控
制的常见使用场景：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Synology Drive 版本控制不适用于对音乐库与视频库的版本控制。这两种场景适合使
用回收站机制来管理。因为音乐和视频库的容量变动幅度较大，在一段时间内进行大量
的删除或者格式转换操作后，磁盘可用空间将迅速下降。不建议将音乐库与视频库加入
到版本控制。&lt;/li&gt;
&lt;li&gt;版本控制不适用于对于应用程序相关数据文件（例如 Docker 容器的映射目录下的相关
文件）的备份，经过长期观察，版本控制对文件修改并不敏感。我往往发现经常变动的
应用程序数据文件一直维持在较老的版本，并没有在应用程序对该文件作出修改后立即
备份上一版本。建议使用 Cloud Sync 或者 Hyper Backup 对应用程序数据文件进行备
份。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;上述问题经过长期使用总结出，如果发现其他问题则会更新此文章。&lt;/p&gt;</description>
    </item>
    <item>
      <title>联系与验证</title>
      <link>https://blog.bktus.com/contact-and-verification/</link>
      <pubDate>Tue, 11 May 2021 09:18:52 +0000</pubDate>
      <guid>https://blog.bktus.com/contact-and-verification/</guid>
      <description>&lt;h2 id=&#34;联系我&#34;&gt;联系我&lt;/h2&gt;
&lt;p&gt;我通过电子邮件与陌生人通信。若需要联系我，请发送邮件至
&lt;a href=&#34;mailto:eric@bktus.com&#34;&gt;eric@bktus.com&lt;/a&gt;（邮箱服务商位于德国并已使用各种措施加强
隐私保护）。如果你不想用明文与我通信，可使用页面底部的 PGP 公钥加密你的邮件。我
一般 2 天内就会回邮件，如果涉及内容较多，我一般会在周末回复。此外，不要发送垃圾
邮件！你可以使用汉语（简或繁）、英语来写邮件。任何情况下，邮件内容须符合&lt;strong&gt;欧盟与
德国&lt;/strong&gt;法律。&lt;/p&gt;
&lt;h2 id=&#34;pgp-公钥&#34;&gt;PGP 公钥&lt;/h2&gt;
&lt;p&gt;我通过邮箱地址 &lt;a href=&#34;mailto:eric@bktus.com&#34;&gt;eric@bktus.com&lt;/a&gt; 发出的邮件一般会附上这个
PGP 密钥的签名，方便邮件接收者查验身份和内容完整性。你也可以通过这个密钥来加密你
的邮件。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEZq5pTxYJKwYBBAHaRw8BAQdA+YEVawOeMQaAPI4rMfycgbDKA7ebPJ0V2r2J
+HPKbz60KnNhdHVybmVyaWMoZm9yIGVtYWlsIG9ubHkpPGVyaWNAYmt0dXMuY29t
PoiZBBMWCgBBFiEEbygCyZlmJ+PDmQF8WJGHNplm8CsFAmauaU8CGyMFCQPCZsoF
CwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQWJGHNplm8CtkrQEA3/PN483C
Ag9+cHR4xZ+GvtLqIDIQsltNlSq77aSWd80A/3lp0WKcd8Ypfc650WgLh9GFZw2N
IcYIqjoO7K2tm7IJuDgEZq5pbxIKKwYBBAGXVQEFAQEHQB5fS+kyqWm+7JvVRIL8
7hzP4Zi1WdQ85Tkr7JbfEOxFAwEIB4h+BBgWCgAmFiEEbygCyZlmJ+PDmQF8WJGH
Nplm8CsFAmauaW8CGwwFCQPCZvkACgkQWJGHNplm8Cs2fgEAlHPl0ucJlgrxOqy9
c21JXPESJBPBENmgBh6vr0VkF/gA/0Mv8aUVpjy4yceRkCxCVpBT6I/9nPqyHlob
NBzq630J
=hYH/
-----END PGP PUBLIC KEY BLOCK-----
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>UNIX伪终端</title>
      <link>https://blog.bktus.com/archives/nwkiqz/</link>
      <pubDate>Wed, 10 Feb 2021 21:36:00 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/nwkiqz/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;最近在研究有关 UNIX 的相关理论知识，在此记录相关重要概念备忘。&lt;/p&gt;
&lt;h2 id=&#34;概述&#34;&gt;概述&lt;/h2&gt;
&lt;p&gt;伪终端是指，对于一个应用程序而言，它看似一个终端，但事实上它并不是一个真正的终
端。 通常一个进程打开伪终端主设备，调用 fork。子进程建立一个新的会话，打开一个相
应的伪终端从设备，将其文件描述符复制到标准输入输出错误，然后调用 exec。伪终端从
设备称为子进程的控制终端。 看起来像一个双向管道，从设备上的&lt;strong&gt;终端行规程&lt;/strong&gt;使得我
们拥有普通管道没有的其他处理能力。&lt;/p&gt;
&lt;h3 id=&#34;伪终端的典型用途&#34;&gt;伪终端的典型用途&lt;/h3&gt;
&lt;h4 id=&#34;网络登录服务器&#34;&gt;网络登录服务器&lt;/h4&gt;
&lt;p&gt;最典型的例子是 telnetd 和 rlogind 服务器。 在 rlogind 服务器和登录 shell 之间有
两个 exec 调用，这是因为 login 程序通常在两个 exec 之间检验用户是否合法。&lt;/p&gt;
&lt;h4 id=&#34;窗口系统终端模拟&#34;&gt;窗口系统终端模拟&lt;/h4&gt;
&lt;p&gt;终端模拟器最为 shell 和窗口管理器之间的媒介。每个 shell 在自己的窗口中执行。
shell 将自己的标准输入、标准输出、标准错误连接到 PTY 的从设备端。&lt;/p&gt;
&lt;h4 id=&#34;script-程序&#34;&gt;script 程序&lt;/h4&gt;
&lt;p&gt;script 程序将终端会话期间的所有输入和输出信息复制到一个文件中。 使用 script 的不
足是必须处理文件中的控制字符。&lt;/p&gt;
&lt;h4 id=&#34;expect-程序&#34;&gt;expect 程序&lt;/h4&gt;
&lt;p&gt;在非交互模式中驱动交互模式运行。&lt;/p&gt;
&lt;h4 id=&#34;运行协同进程&#34;&gt;运行协同进程&lt;/h4&gt;
&lt;p&gt;当通过管道与协同进程通信时，标准 I/O 库会完全缓冲标准输入和标准输出，从而引起死
锁。 现在协同进程的标准输入和标准输出就像终端设备一样，所以标准 I/O 库会将这两个
流设置为行缓冲。&lt;/p&gt;
&lt;h4 id=&#34;观看长时间运行程序的输出&#34;&gt;观看长时间运行程序的输出&lt;/h4&gt;
&lt;p&gt;由于重定向到文件时，标准 I/O 库将完全缓冲它的标准输出。&lt;/p&gt;
&lt;h3 id=&#34;打开伪终端设备&#34;&gt;打开伪终端设备&lt;/h3&gt;
&lt;p&gt;PTY 表现得就像物理终端设备一样，因此应用程序就无需在意它们在使用的是何种设备。
在伪设备可用之前，它的权限必须设置，以便应用程序可以访问它。&lt;/p&gt;</description>
    </item>
    <item>
      <title>UNIX 终端I/O</title>
      <link>https://blog.bktus.com/archives/0flvi2/</link>
      <pubDate>Wed, 10 Feb 2021 15:28:30 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/0flvi2/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;我阅读并且学习了有关于 UNIX 系统终端 I/O 相关的内容。在此记录一些比较关键的概
念。&lt;/p&gt;
&lt;h2 id=&#34;引论&#34;&gt;引论&lt;/h2&gt;
&lt;p&gt;终端 I/O 十分复杂，原因之一是它应用于许多事物。&lt;/p&gt;
&lt;h2 id=&#34;综述&#34;&gt;综述&lt;/h2&gt;
&lt;p&gt;终端 I/O 的两种工作模式：规范模式输入处理（默认）、非规范模式输入处理。&lt;/p&gt;
&lt;p&gt;规范模式下，对于每一个读请求，终端驱动程序最多返回一行。&lt;/p&gt;
&lt;p&gt;可以认为终端设备是由内核中的终端驱动程序控制的，每一个终端设备都有一个输入队列和
一个输出队列。&lt;/p&gt;
&lt;p&gt;开启回显功能时，在输入队列和输出队列之间有一个隐含连接。&lt;/p&gt;
&lt;p&gt;输入队列长度是有限值。&lt;/p&gt;
&lt;p&gt;输出队列虽然也有限，但是程序并不能获取这个值。在输出队列要填满时，内核会直接将写
进程休眠。&lt;/p&gt;
&lt;p&gt;大多是 UNIX 系统在一个称为终端行规程的模块中进行全部的规范处理。该模块在内核通用
读写函数和实际设备驱动程序之间。&lt;/p&gt;
&lt;p&gt;所有可以检测和更改的终端设备特性都包含在 termios 结构中。&lt;/p&gt;
&lt;p&gt;使用 tcsetattr 和 tcgetattr 可以设置终端选项进而控制终端。&lt;/p&gt;
&lt;h2 id=&#34;特殊输入字符&#34;&gt;特殊输入字符&lt;/h2&gt;
&lt;p&gt;POSIX 定义了 11 个在输入时要特殊处理的字符。在这 11 个特殊字符中，9 个字符的值可
以任意更改。&lt;/p&gt;
&lt;p&gt;为了更改特殊字符，需要修改 termios 结构中的 c_cc 数组的相应项。&lt;/p&gt;
&lt;p&gt;POSIX 允许禁止使用这些字符。&lt;/p&gt;
&lt;h2 id=&#34;终端标识&#34;&gt;终端&lt;strong&gt;标识&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;在大多数 UNIX 系统版本中，控制终端名字一直是/dev/tty。&lt;/p&gt;
&lt;h2 id=&#34;规范模式与非规范模式&#34;&gt;规范模式&lt;strong&gt;与非规范模式&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;规范模式：发送一个请求，当一行已经输入以后，终端程序立即返回。以下几个条件造成读
返回：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;所请求的字节数已经读到时，无需读一个完整的行。&lt;/li&gt;
&lt;li&gt;当读到一个行界定符号&lt;/li&gt;
&lt;li&gt;捕捉到信号，并且该函数不再自动重启&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;非规范模式：时输入数据不装配成行，不处理特殊字符。当读取指定量的数据后，或者超过
指定量的时间后，通知系统返回。该模式下没有关闭对信号的处理，用户始终可以键入一个
触发终端产生信号的字符。&lt;/p&gt;
&lt;h2 id=&#34;终端窗口大小&#34;&gt;终端窗口大小&lt;/h2&gt;
&lt;p&gt;大多数 UNIX 系统都提供了一种跟踪当前终端窗口大小的方法，当窗口大小变化的时候，使
内核通知前台进程组。内核未每个终端和伪终端都维护了一个 winsize 结构。&lt;/p&gt;</description>
    </item>
    <item>
      <title>通过Gparted Live ISO可引导镜像调整硬盘分区大小</title>
      <link>https://blog.bktus.com/archives/b777y7/</link>
      <pubDate>Tue, 09 Feb 2021 17:01:59 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/b777y7/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;手上有一张安装了 Openwrt 的 8G 的 TF 卡，根分区的容量已经不太能够满足我的使用需
求了。所以开始着手扩大根分区的大小。根分区的所使用的的文件系统格式是 Ext4。首
先，尝试使用 DiskGenius 等 Windows 下的工具进行扩容，很遗憾都不可以。于是准备使
用 Gparted 进行扩容。由于该工具需要在 Linux 环境下运行，我不太想安装为此安装一个
Linux 发行版虚拟机所以使用 Gparted 的轻量 ISO 镜像配合 Virtual Box 虚拟机进行使
用。&lt;/p&gt;
&lt;h2 id=&#34;准备工作&#34;&gt;准备工作&lt;/h2&gt;
&lt;p&gt;首先下载安装 VritualBox 虚拟机和 VM VirtualBox Extension Pack。VirtualBox 并默认
不支持 USB 外设操作，所以要安装而外后者来为 VirtualBox 添加 USB2.0、USB3.0 等外
设支持。 &lt;a href=&#34;https://www.virtualbox.org/wiki/Downloads&#34;&gt;VirtualBox 下载地址&lt;/a&gt; &lt;a href=&#34;https://www.virtualbox.org/wiki/Downloads&#34;&gt;VM
VirtualBox Extension Pack&lt;/a&gt; 以上两者下
载完后，先安装 VirtualBox。 然后安装 VM VirtualBox Extension Pack，具体在首选项
界面扩展栏目中安装。 下载 GParted Live CD/USB/HD/PXE Bootable Image，&lt;a href=&#34;https://gparted.org/download.php&#34;&gt;下载链
接&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&#34;步骤&#34;&gt;步骤&lt;/h2&gt;
&lt;p&gt;创建虚拟机，分配单核、内存 512MB 即可，可以不创建虚拟硬盘。 在虚拟机设置界面中，
在 USB 设备栏目中启用 USB 控制器，根据需要选择 USB2.0 或者 USB3.0。 在储存栏目光
驱下，选择下载好的 ISO 镜像，启动虚拟机。 在第一个引导菜单中选择&lt;strong&gt;第一项&lt;/strong&gt;。 而
后，按步骤一次选择或者输入&lt;strong&gt;Dont touch keymap， 26（简体中文），0（启动 X Window
系统）&lt;/strong&gt;。 然后就能够进入图形界面了，点击桌面上的 Gparted 工具镜像分区操作。 分
区后，记得点击应用。&lt;/p&gt;</description>
    </item>
    <item>
      <title>YouCompleteMe C/C&#43;&#43; VIM  CMake 工程 代码提示不可用问题</title>
      <link>https://blog.bktus.com/archives/st6w66/</link>
      <pubDate>Sat, 06 Feb 2021 22:44:45 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/st6w66/</guid>
      <description>&lt;h2 id=&#34;youcompleteme-介绍&#34;&gt;YouCompleteMe 介绍&lt;/h2&gt;
&lt;p&gt;如果安装完&lt;a href=&#34;https://github.com/ycm-core/YouCompleteMe&#34;&gt;YouCompleteMe&lt;/a&gt;并配置好后
（本站有过程记录，&lt;a href=&#34;https://blog.bktus.com/archives/2658&#34;&gt;点击这里查看&lt;/a&gt;），就可以
使用单文件来检测代码提示效果了。但是，当 S&amp;amp;E 打开他的 C/C++工程时，却发现代码提
示、跳转等功能不能正常使用。在查阅文档后，S&amp;amp;E 发现原来是 YouCompleteMe 相关的索
引数据库没有建立，相关的编译选项并不正确，所以 YouCompleteMe 所使用的的 clangd
就不能将多个源文件联系起来。&lt;/p&gt;
&lt;h2 id=&#34;建立-cc-vim-代码提示索引的方法&#34;&gt;建立 C/C++ VIM 代码提示索引的方法&lt;/h2&gt;
&lt;p&gt;如果是使用 CMake 建立工程，则可以在 CMakeList.txt 中加入&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;set( CMAKE\_EXPORT\_COMPILE\_COMMANDS ON )
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;或者在命令行 cmake 后加上&lt;code&gt;-DCMAKE_EXPORT_COMPILE_COMMANDS=ON&lt;/code&gt;也行&lt;/p&gt;
&lt;h2 id=&#34;建立索引的原理&#34;&gt;建立索引的原理&lt;/h2&gt;
&lt;p&gt;YouCompleteMe 读取由构建系统 CMake 生成的编译数据库（通常名字叫做
compile_commands.json），这样就可以完成对于工程文件的索引。而编译数据库包含项目
中每个编译单元的编译器调用。YouCompleteMe 会寻找打开文件所在目录中的
compile_commands.json，如果没找到会递归地向上查找这个文件。如果在它找到
.ycm_extra_conf.py 之前，找到了 compile_commands.json，那么它就会停止搜索，然
后，让 clangd 处理接管并处理该文件中含有的标志。 在完成上述这些操作
后，YouCompleteMe 的相关功能就可以正常使用了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Vim 代码提示插件 YouCompleteMe 安装与配置</title>
      <link>https://blog.bktus.com/archives/xocjog/</link>
      <pubDate>Sat, 06 Feb 2021 21:45:52 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/xocjog/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;对于在 Vim 下的 C/C++程序编写，如果有代码提示插件会大大提高编写效率。大型 IDE 用
的多了，刚回归 Vim 的 S&amp;amp;E 比较依赖这个。正好 YouCompleteMe 能够满足他的相关需
求。索性把安装与配置的过程记录在这里，以供下次回忆使用。 除了
C/C++，YouCompleteMe 支持 Java、Go、C#、Objective-C、CUDA 等，可以说是比较强大
了。但是话说，写 Java 为什么要用 Vim 呢？IDEA 貌似更好。 使用后发现这插件还支持
代码跳转、引用查找、修改函数名和格式调整等操作，挺方便。 Giuhub 仓库地
址：&lt;a href=&#34;https://github.com/ycm-core/YouCompleteMe&#34;&gt;https://github.com/ycm-core/YouCompleteMe&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;前置条件&#34;&gt;前置条件&lt;/h2&gt;
&lt;p&gt;安装最新的 YouCompleteMe 插件需要满足一些条件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vim 8.1 以上 并且启用了 Python3 扩展支持（本站有过程记录，&lt;a href=&#34;https://bktus.com/archives/2646&#34;&gt;点击这里查
看&lt;/a&gt;）&lt;/li&gt;
&lt;li&gt;GCC 8 以上 或者 Clang 7 以上&lt;/li&gt;
&lt;li&gt;Python3.6 以上编译的时候有&amp;ndash;enable-shared 选项（一般包管理器安装都带有）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于 Debian 10， 通过包管理器安装的 Gcc 版本为 8.3.0。 然后可以通过以下命令查看
编译器版本&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% cc -v
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;对于 python3 的版本，使用以下命令查看&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% python3 --version
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;对于 Vim 版本，使用执行以下命令查看&lt;/p&gt;</description>
    </item>
    <item>
      <title>Vim主题 spf13-vim.sh 的安装与使用</title>
      <link>https://blog.bktus.com/archives/1avhtp/</link>
      <pubDate>Sat, 06 Feb 2021 21:07:21 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/1avhtp/</guid>
      <description>&lt;h2 id=&#34;vim-主题介绍&#34;&gt;Vim 主题介绍&lt;/h2&gt;
&lt;p&gt;我经常使用 vim 为在 Linux 下的主要的代码编辑器。每当 SSH 进入一个新的开发系统环
境，为了编写方便，他总是需要手动安装 Vim 并配置各类常用插件。spf13-vim.sh 是一个
使用于 Vim 的插件和相关资源的发行版。一条命令，即可以自动安装常用的配套的插件环
境。 Github 仓库地
址：&lt;a href=&#34;https://github.com/spf13/spf13-vim&#34;&gt;https://github.com/spf13/spf13-vim&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;心得&#34;&gt;心得&lt;/h2&gt;
&lt;p&gt;我感觉这个就好像快速安装了一个以 Vim 为核心的 IDE（可以类比 Vscode）。然
后，spf13-vim.sh 产生一个比较规范的 vim 配置文件层次结构，方便后来再添加其他插
件，也避免无规划地手动添加插件产生的杂乱的配置文件。而且，把相关插件的优化和配置
工作丢给它后，省心了不少。&lt;/p&gt;
&lt;h2 id=&#34;安装&#34;&gt;安装&lt;/h2&gt;
&lt;p&gt;前置条件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;git&lt;/li&gt;
&lt;li&gt;curl&lt;/li&gt;
&lt;li&gt;vim 7.3 以上&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本站有安装 Vim 8.2 的相关过程记录：&lt;a href=&#34;https://bktus.com/archives/2646&#34;&gt;点击这里查
看&lt;/a&gt; 对于 Debian 10 可以简单地执行以下命令安装
git 和 curl&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% sudo apt install git curl
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后对于 Unix/Linux、Mac OS 等，执行以下命令一键安装 spf13-vim.sh&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% curl https://j.mp/spf13-vim3 -L &amp;gt; spf13-vim.sh &amp;amp;&amp;amp; sh spf13-vim.sh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;（对于 Windows 系统，请参考 Github 仓库中的 ReadME.md）&lt;/p&gt;</description>
    </item>
    <item>
      <title>Vim 8.2 源码编译安装 添加Python3扩展</title>
      <link>https://blog.bktus.com/archives/4vkp8w/</link>
      <pubDate>Sat, 06 Feb 2021 18:51:15 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/4vkp8w/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;为了安装 YouCompleteMe 这类插件，需要将 Vim 升级至比较高的版本并且启用 Python3扩
展。所以，这里提供的是通过源码安装 Vim 最新版本的过程记录。 这里使用到的 Vim源代
码仓库地址：&lt;a href=&#34;https://github.com/vim/vim/&#34;&gt;https://github.com/vim/vim/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;编译安装默认版本&#34;&gt;编译安装默认版本&lt;/h2&gt;
&lt;p&gt;在编译安装之前先要安装相关的工具以及依赖&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% sudo apt install git make clang libpython3-dev
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;选择适当的目录执行克隆命令&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% git clone https://github.com/vim/vim.git
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;克隆成功后会出现 vim 目录，进入该目录下的 src 目录&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% cd vim/src
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;执行编译（为了加快速度可以替换执行&lt;code&gt;% make -j4&lt;/code&gt;来并行编译）&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% make
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;执行测试&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% make test
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;默认安装到/usr/local 目录下&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;% sudo make install
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;开启python3扩展支持&#34;&gt;开启Python3扩展支持&lt;/h2&gt;
&lt;p&gt;在上述操作完成后，打开该目录下的Makefile文件，找到&lt;code&gt;&amp;quot;CONF_OPT_PYTHON3 = --enable-python3interp&amp;quot;&lt;/code&gt;并取消注释该行，保存。 执行命令更新编译参数&lt;code&gt;make reconfig&lt;/code&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>站点声明</title>
      <link>https://blog.bktus.com/site-declaration/</link>
      <pubDate>Fri, 29 Jan 2021 13:19:56 +0000</pubDate>
      <guid>https://blog.bktus.com/site-declaration/</guid>
      <description>&lt;h2 id=&#34;非营利性个人博客&#34;&gt;非营利性个人博客&lt;/h2&gt;
&lt;p&gt;本网站是一个非营利性个人博客，专注于分享知识和信息，与商业或政治活动无关。我致力
于为访问者提供有价值的内容，以促进学习和交流。&lt;/p&gt;
&lt;h2 id=&#34;版权所有&#34;&gt;版权所有&lt;/h2&gt;
&lt;p&gt;本站所有内容，包括文字、图片、视频、链接和代码等，均为本站所有人Saturneric的财
产。Saturneric授予访问者浏览这些内容的权利，以便访问者能够从中获取知识和启发。除
非另有明确授权，否则Saturneric保留对上述内容的一切权利。&lt;/p&gt;
&lt;h2 id=&#34;使用条款&#34;&gt;使用条款&lt;/h2&gt;
&lt;p&gt;访问本站及其内容的访问者应该明确承认并接受以下条款：我不对使用本站提供的方法、技
术或其他内容可能导致的任何直接或间接损失负责。访问者在使用本站提供的任何信息或资
源时应自行承担风险。如果您不同意本声明的任何条款，请立即停止访问本站。&lt;/p&gt;
&lt;h2 id=&#34;转载授权和法律责任&#34;&gt;转载授权和法律责任&lt;/h2&gt;
&lt;p&gt;如果您希望转载本站的内容，您需要事先获得我的书面授权，并在转载内容末尾明确标注本
站的来源网址。未经授权擅自转载本站内容的行为将承担法律责任，我保留追究法律责任的
权利。我鼓励合法合规的转载行为，但同时也希望转载者能够尊重原创作者的劳动成果。&lt;/p&gt;
&lt;h2 id=&#34;侵权投诉&#34;&gt;侵权投诉&lt;/h2&gt;
&lt;p&gt;如果任何单位或个人认为本站的内容侵犯了其合法权益，应及时向我提交书面反馈，并提供
有效的身份证明、权属证明以及详细的侵权情况证明。我将尽快处理侵权投诉，并采取适当
的措施以移除涉嫌侵权的内容。&lt;/p&gt;
&lt;h2 id=&#34;法律适用&#34;&gt;法律适用&lt;/h2&gt;
&lt;p&gt;本站点的服务器和数据都位于&lt;strong&gt;德国境内&lt;/strong&gt;，所以本站点遵守&lt;strong&gt;德国法律和欧洲联盟&lt;/strong&gt;
法律。对于本声明未涵盖的事项，我将遵循适用的法律规定。如果本声明的内容与上述法律
存在任何冲突，我将以上述法律的规定为准。我将尽最大努力确保本站内容的合法性和合规
性，但对于访问者在其他法域下的访问或使用行为，我不承担任何法律责任。&lt;/p&gt;
&lt;h2 id=&#34;免责声明&#34;&gt;免责声明&lt;/h2&gt;
&lt;p&gt;本站的内容仅供参考和学习，不构成任何形式的专业意见或建议。访问者在使用本站提供的
信息时应自行判断和决策，我不对任何因使用本站信息而导致的任何损失负责。对于本站链
接到的其他网站或第三方提供的内容，我不对其准确性、完整性或可靠性进行担保。&lt;/p&gt;</description>
    </item>
    <item>
      <title>知行论（四）</title>
      <link>https://blog.bktus.com/archives/0tui6f/</link>
      <pubDate>Sat, 26 May 2018 01:37:57 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/0tui6f/</guid>
      <description>&lt;p&gt;所知，虽然是对于一个人的所知。但是对于处世是有益处的。所知愈多，所思就会越深刻。
但是这种知不是一味的去知。要知道世界上没有绝对正确的知，没有全部清楚的知，没有绝
对权威的知，没有处于本真的知。有人要是说他有真知，这是不可能的。神要是说他有真
知，我不知道它到底有没有。如果一味接受外来的知，这些知就是死的知。死的知是没有去
进行析的过程的知。没有我用我所知去析这些知，转化为我之知而被我所用。我不这样做。
这种知不是我之知，就不能真正被我灵活运用，我只是知罢了。若如果没办法运用的的话，
就不能将它用于思。如果一味的接受外来的知，我是没有能力全部析这些知的。一味接受外
来的知的人，也是没有析这个过程的，这些知是不能够被他们灵活运用的。我不这样做。能
够析，有所领悟是一件快乐的事。能有所知，有所析，有所知，有所法，行才能够成功。知
之，析之，思之，是知的道理。 所行，成功了。如果我们以为所行之法就是通用的，认为
此法是绝对了，这就错了。成功之法，是根据所知，所思产生的。成功的道路上有的变数是
我所不知道的。变数没有改变，法是畅行的的。如果改变的话，法就不能畅通，就不能让行
成功。所以说古无定知，行无定法。我得到了法，我按照它来行，它让事物发生了改变。但
是事物的改变确实是它本源发生了改变，但是我只能感知到我所能够感知的变化。简单的变
化可以感知，但是其复杂的变化是难以感知的。所以，行要谨慎，不骄傲。谨慎的人是有很
大的灵活性的。使用法，骄傲的人是不会变通的。但是谨慎的人能够应对多样的变化。谨慎
的人得以使用他们全部所知，全部所思来使用法。不谨慎的人只能看到事物的表象武断地判
断。这样会有所损失的。所以谨慎而行，不轻率，成功的方法。谨慎的人可以应对万变，能
够运用上他们全部的所知所思，容易让行法的过程顺畅。法也在他们使用的过程中畅顺。&lt;/p&gt;</description>
    </item>
    <item>
      <title>知行论（三）</title>
      <link>https://blog.bktus.com/archives/er6eer/</link>
      <pubDate>Sat, 26 May 2018 01:36:26 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/er6eer/</guid>
      <description>&lt;p&gt;行的过程中，我们一定有目标。但是众人渴求目标迫切想要达到目标，是不容易得到的。应
当处在不求的状态，但心中知道有这个目标。迫切想达到，心里必然渴，这样就不能达到静
的状态，不静就会浮躁，浮躁就会缺失很多东西。这样所知是片面的，所思也是不周全的。
所以，处于静的状态不渴求才是行的方法。心思不全放在目标上，这样知的范围就可以广很
多，像平常一样，这样才可能成功。 行的过程中，要用心。用心，就必然要专心。心不专
一是达不到目标的。心不专一，我所知与所思不能全部发挥出来。怎么心专一，行事前一定
要有所知，有所思，让所思产生法。有所知，还没有行之时心就能专一。有所思，有所法而
行，心就能定。无思则无法，心就会乱。能够聚集心神的心就能专心。心神如果是散开的
话，心就是乱的。什么是心专一，心里没有杂念，没有其他的事。专心的人行的时候才能够
顺畅，才可能成功。&lt;/p&gt;</description>
    </item>
    <item>
      <title>知行论（二）</title>
      <link>https://blog.bktus.com/archives/9h5dq9/</link>
      <pubDate>Sat, 26 May 2018 00:00:07 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/9h5dq9/</guid>
      <description>&lt;p&gt;论及行。行，是难做到的。我们认为我们获得了知，我们就能够行。并不是这样的，事物的
变化难以预料，这不是我们可以预先知道的。所以行必须谨慎，用来防范难以预料的变化。
事物的变数多是行难的原因之一。 知行并不是合二为一的。我们认为知了就行，认为行一
定会成功。知道了规律方法后就去行。但我们所知道的规律方法，其运用到的情况都是我们
构想出来的，我们所举得出的例子，所能够想得出的细节，都是源于我们的思。我们所思，
会出现荒谬的地方，不周全的地方。若果就这样行的话，如果遇到我们所思之外的细节，我
们就会慌。如果出现我们所思之外的例子，我们的行就会停止。我们时常行，才是成功的方
法。怎么行，先知然后行。怎么知，行后自然知。 我行的途中，一定会有言论制止我。会
有言论论及我的行的错误之处，我的知的错误之处。如果我就这样听从了，停止了，是不能
成功的。如果我一点都听不进去，一意孤行，也难以成功。该怎么办。他人所论及的，他人
所知的，都是处于他人所感知的，所思，所行而形成的。没有所谓的绝对真知，也没有所谓
的权威之知，更没有什么永恒不变之知。我会观察这些论断的表象，揣测它们的本意，虽然
不能得到它们本源的意思，但是一定会有所收获。所以，我们不妨听之，思之，用行来检
验。如果确实有用，我们就用，但不是盲从。如果不行，就坚持我们的见解。知之，在行之
的时候要时常思之，这是好事。行有了成功的结果，就是行就是成功的。虽然造成成功的结
果的方法可能不适用于所有情况，但对于我自己的角度，它就是成功的。所以，我之行能否
成功，是不能凭借他人所说来预测的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>知行论（一）</title>
      <link>https://blog.bktus.com/archives/y8d47o/</link>
      <pubDate>Fri, 25 May 2018 00:00:25 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/y8d47o/</guid>
      <description>&lt;p&gt;出于偶然，我写下了这些文字。由于一些原因，我比较浮躁，而写这些东西能让我静得下心
来。这些文字关于一些理论。这也是一把哲学的武器与防具，集合成理论后就能够变得锋
利，变得坚固。它能够帮助我经受住生活上的挑战。知行论只是其中之一。它源于我的生
活，我读过的书，我的思考。以下进入正文。 论及知，我们用眼睛观察事物，用耳朵听它
的声音，用手去抚摸它感受它，我们就认为我们感知了这个事物。我们用大脑思考这件事，
用心去感知它，我们就认为我们了解了这件事物。但是，我们所看见的，所听到的，所抚摸
到的，都是我们的感官能够感觉到的。我们怎么知道我们的感官感觉到的是事物的本真呢？
我们感知事物只能够凭借感官，它们感知的事物是怎么样的源于它的构造，哪能不能够存在
一套构造完全不同的感官，它们感觉到的事物的样子与我们的毫不相同呢。这是存在的，那
么说明我们没有能力知道事物的本质。 我们所思想的，我们所能够感知的都出自于我们的
脑心，但是我们的脑心都是外力所塑造的，并且我们所思都是含有我们的愿望在其中的。什
么是我们的愿望呢？我们的心思是寄托在我们的身体上的。我们身体受到伤害，伤害我们的
脑心会觉得伤心；我们的身体得到了什么，我们的脑心也会欢喜。我们的所思也蕴含有其他
人的思想。我们生下来是一张白纸，我们的老师教我们知识，我们老师所教的知识，也是我
们老师的老师教给他的。所以我们知识源于他人的脑心，他人所思蕴含于知识中并通过教授
传给我。所以我们所思都是从我们的角度出发的，并不是关于事物本质的思。我常常以为思
考的越深入就越接近事物的本真，然而并不是这样。我所思，其实是将事物用我的感觉读入
脑心之中，然后以我的方式加工。 这样所感知的事物，所了解的事物都不是事物的本质。
这样我就知道了，事物的本源是不能准确被感知的。事物的真理也是不能被准确思考的。这
就是知的局限性。&lt;/p&gt;</description>
    </item>
    <item>
      <title>反质变的直接促成</title>
      <link>https://blog.bktus.com/archives/rr970y/</link>
      <pubDate>Sun, 14 May 2017 00:00:51 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/rr970y/</guid>
      <description>&lt;p&gt;虽然说，量变是质变的必要准备。但有一些特定情况下，量变的积累会由于突发事件的发生
导致反质变。这种反质变是威力巨大的，非常快速的，而且是几乎不可逆转的。量积累越
深，反质变来的越猛烈。反质变的条件不仅仅是突发事件这个表面原因。突然触发这个事件
后，由于量变大量地积累，以及自我对于量变的内部的具体信息把握缺失从而产生的怀疑，
最终导致了反质变的发生。反质变发生后，表面上，在他人看来，自我的外在表现可能并没
有改变，但是自我对于事物的看法迅速发生了根本的改变。这种反质变对于自我的思想的冲
击是非常大的，而且在但时间内会对自我的生理心理造成巨大的冲击。日后，虽然量变还在
可能继续积累，但是反质变对于自我的思想的改变以及无法挽回。 举个例子，比如我认为
一个人是可以相信的，所以我觉得我不用去详细了解这个人的具体思想。现实的表现也逐步
印证我的直觉，我继续相信这个人，信任逐渐加深。这样，我对于这个人的信任就像操作黑
盒子一样，不用了解内部运作也知道这个人是可信任的。这样的信任是程度很大的，但也是
极其敏感的。所以，一旦有一次发生了失信事件，不管这个人是不是真正失信，也不管事件
多小，只要从我的角度观察这个事件的表现，然后以我单方面判断后认为这很有可能是失信
表现后，反质变就发生了。这个人的行为首先冲击我的身心，直接造成我产生了被欺骗的感
觉。然后，我对于这个人的看法也发生了根本的改变，虽然表面上我仍然对这个人以微笑。
以后这个人的表现是否还是值得信任的表现对于这个反质变的作用是微乎其微的。当我还想
认为可以相信这个人的时候，这个反质变的作用必然会形成一种强大阻力。 所以，当收到
别人无猜的信任的时候要珍惜，因为这种信任是很深的，也是极其敏感的。虽然自认为行为
是在理论上可以理解的，但是对于对方并不是这样。一旦发生突发事件，这段信任会发生不
可逆转的转变。 这种过程对于其他相同或者相似的条件仍然成立。&lt;/p&gt;</description>
    </item>
    <item>
      <title>对一段挫折进行反思</title>
      <link>https://blog.bktus.com/archives/lb5b92/</link>
      <pubDate>Fri, 12 May 2017 21:02:06 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/lb5b92/</guid>
      <description>&lt;p&gt;在现实生活中，我不断遇到各种挑战和难题。当面对这些问题时，我经常感到震惊和无措。
然而，当我冷静下来并对问题进行深入分析后，我通常会尝试在现有的体系和框架内寻找解
决方案。对于一些常规问题，这种方法可能有效。但有时，问题的根源恰恰在于这个体系本
身。我过去常常试图通过加强现有体系来解决问题，但这往往效果有限，甚至无法根本上解
决问题。这样的做法可能导致我越陷越深，最终无法摆脱困境。&lt;/p&gt;
&lt;h3 id=&#34;学习模式的挑战&#34;&gt;学习模式的挑战&lt;/h3&gt;
&lt;p&gt;我的学习过程中从未真正质疑过我所遵循的学习模式。然而，在一次严重的挫折之后，我开
始意识到这可能是个人表现问题的根源。随着问题的加剧，我发现自己面临前所未有的挑
战。起初，我感到非常迷茫，认为一切都很荒谬。尝试了一些方法后，我发现仅仅加强原有
的学习模式并不能带来显著的改进。最终，我几乎不知该如何应对。&lt;/p&gt;
&lt;h3 id=&#34;直面恐惧&#34;&gt;直面恐惧&lt;/h3&gt;
&lt;p&gt;问题依然存在，我必须找到解决它的方法。面对恐惧的唯一方法就是勇敢直面。在最近的一
次挫折之后，我决定挑战我的学习模式。正如量子理论颠覆了传统的物理观念，我也意识到
需要改变我的学习方式。我深入分析了我的学习问题，发现其根源不仅仅是粗心或运气不
佳。实际上，我缺乏勇气去面对更深层次的基础问题。我一直相信自己的智力没有问题，但
从小学到初中，我的基础问题已经多次显露，只是我没有给予足够的重视。 在初中时期，
我的信息学老师曾提醒我，我在数学方面的粗心可能是基础问题的表现。这是我第一次听到
这样的观点，但当时我并没有重视，因为我缺乏深入分析问题的能力。 进入高中后，这个
问题变得更加明显，我的基础知识缺陷完全暴露。高中阶段的考试对基础知识的要求更高，
仅凭智力已无法掩盖基础问题的严重性。那么，基础到底包括哪些方面呢？它涉及解决问题
的思路的严谨性、操作的准确性，以及基础知识的掌握程度。现在，我可以坦率地说，我的
基础知识确实存在严重问题，这是我以前一直不敢面对的。 例如，在科学计数法、单位转
换、基本物理单位概念和数学除法运算等方面，我存在明显的不足。以前，我解决问题时往
往忽视细节，比如是否可以取零、是否有意义等。尤其是在基础知识和概念方面，我从未重
视过，甚至轻视它们。我错误地认为这些知识在具体问题中用处不大。但现在，我认识到这
是一个严重的误解。&lt;/p&gt;
&lt;h3 id=&#34;重新审视学习方法&#34;&gt;重新审视学习方法&lt;/h3&gt;
&lt;p&gt;我发现自己的学习方法存在问题，我在问题分析上不够细致和深入。面对问题时，我未能从
根本上进行分析，也缺乏对问题背后原因的深入思考。我意识到，对问题的分析不仅仅是表
面的处理，而是需要找到其背后的深层原因，并对自己的现状进行批判性的思考。这也表
明，在面对挫折时，我们需要保持心理承受能力，并从中吸取经验教训。 因此，学习中的
缺失提醒了我，必须从根本上解决问题，回归到基础知识的学习上。忽视基础知识和概念是
错误的，这是我们不能忽视的关键因素。我现在认识到，只有充分理解和掌握基础知识和概
念，才能更好地解决问题并取得进步。通过这种方式，我可以在学习和生活中取得更大的成
就，更好地应对未来的挑战。&lt;/p&gt;</description>
    </item>
    <item>
      <title>God Engine 标准定义（一）</title>
      <link>https://blog.bktus.com/archives/j8cnyr/</link>
      <pubDate>Sat, 06 May 2017 13:02:22 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/j8cnyr/</guid>
      <description>&lt;p&gt;好几个月前，思想中浮现了一种新的东西。按照我的哲学观念，我把它命名为&lt;strong&gt;God
Engine&lt;/strong&gt;。依照现在的技术，这个东西还没有足够的条件存在。希望以后我可以亲手缔造。
所以，姑且把这东西写出来备忘。&lt;/p&gt;
&lt;h2 id=&#34;概述&#34;&gt;概述&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;God Engine&lt;/strong&gt;是具有原子微观性模型宏观性智慧性多空间时间性异步计算性的模拟引擎。
其底层直接与硬件沟通，其通过网络与其他应用程序沟通。通过基础宇宙模型的标准数学物
理法则定义，配以宇宙模型插件，依据时间线，进行详尽的对象间互相的的关系作用的分
析，从而提供可靠的对象间的稳定关系及对象组的可靠宏观性质。操作者通过在对象组之间
建立联系，并提供基础的模型，引擎将根据这些信息逐步构建庞大而复杂的对象组，引擎将
会进行对象组之间原子微观的关系分析学习，得出较大对象组的稳定宏观性质。这些初步形
成的可靠的模型将储存到数据库中，为其他模型的分析提供依据。最终，引擎得出使用者希
望得到的最终稳定的模型，然后其将对历史信息进行最后的分析筛选，得出模型的详细定义
及逻辑描述，为人类社会提供可靠的成品模型。&lt;/p&gt;
&lt;p&gt;简而言之，这个引擎具备了原子微观性模型、宏观性智慧性、多空间时间性和异步计算性。
它可以通过与其他应用程序的网络沟通，将底层直接与硬件沟通的操作，转化为人们可以理
解的信息。该引擎是基于宇宙模型的标准数学物理法则定义的，并配以宇宙模型插件。它能
够对时间线上各对象间的关系作用进行详尽的分析，并提供可靠的对象间的稳定关系及对象
组的可靠宏观性质。操作者可以在对象组之间建立联系，并提供基础的模型，引擎将根据这
些信息逐步构建庞大而复杂的对象组，并进行对象组之间原子微观的关系分析学习，得出较
大对象组的稳定宏观性质。这些初步形成的可靠的模型将储存到数据库中，为其他模型的分
析提供依据。&lt;/p&gt;
&lt;h2 id=&#34;逻辑组成部分&#34;&gt;逻辑组成部分&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;数学运算模块：为引擎提供数学运算支持，处理各种数学上的原子运算。&lt;/li&gt;
&lt;li&gt;逻辑运算模块：为引擎提供逻辑运算支持，处理各种逻辑上的原子运算。&lt;/li&gt;
&lt;li&gt;数理控制器：将复杂的数学，逻辑上的问题转化为原子运算，协调数学运算模块与逻辑运
算模块的工作。&lt;/li&gt;
&lt;li&gt;空间控制器：管理引擎实例中所使用到的特定关联的空间，定义空间属性，协调空间内的
运算资源占用，收集模型控制器中产生的信息，汇总成初级信息。&lt;/li&gt;
&lt;li&gt;模型控制器：定义空间中的特定关联的模型，处理各模型之间的相互作用，收集模型产生
的原始信息，并进行初始整理。&lt;/li&gt;
&lt;li&gt;时间线控制器：每个空间对应唯一的时间线控制器，协调空间内的秩序，控制和记录空间
模拟进程。&lt;/li&gt;
&lt;li&gt;信息处理模块：具有信息筛选，分析，概括，整理能力。处理各个空间控制器所提交的初
级信息，产生有效信息，归档到实例数据库内。&lt;/li&gt;
&lt;li&gt;实例数据库：储存实例的基础信息，及产生的原始信息，有效信息，最终信息。&lt;/li&gt;
&lt;li&gt;信息归纳模块：根据数据库中储存的各种有效信息，进行分析汇总，归纳出最终信息，并
储存到实例数据库内。&lt;/li&gt;
&lt;li&gt;实例指导模块：根据数据库中的最终信息，进行最终分析，并依据分析对实例模拟进程进
行调节，让模拟进程向最终结果方向发展。&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>关于物联网形式的思考（二）</title>
      <link>https://blog.bktus.com/archives/3vqrz7/</link>
      <pubDate>Thu, 20 Oct 2016 00:00:03 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/3vqrz7/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://blog.bktus.com/archives/3116&#34;&gt;上一篇文章&lt;/a&gt;粗略的谈到了我的脑海中的萌发的
关于物联网形式去中心化的构想，这周我对我心中的萌芽进行了进一步的思考。现在，我主
要来阐述一下在我脑海中的构想框架，可能会有些疏漏，望指正。&lt;/p&gt;
&lt;p&gt;**内容提示：**这篇文章主要来概述我的物联网去中心化的观点与去中心化后物联网的公有
网络主要组织形式，为了大家容易接受，不要被我脑子里的枯燥的逻辑思维所烦躁，我举了
一些例子来说明。这样损失了一些专业性，望谅解。&lt;/p&gt;
&lt;p&gt;在我的构想中，连接物联网中的物体都是平等的。它们都有各自的功能，比如说烧水，煮
饭，做酸奶（可能我现在有点饿了），当然，这个物体也可能是机器人。如果工程师想让它
们连接到物联网，它们不用自己从头开发，只需要将现成的物联网终端模块添加到它们的电
器（物体）中，然后依照标准化协议操作这个模块就可以了。可以说，只要添加了这个物联
网模块，这个孤独的物体就可以用它和其他拥有这个模块物体说话了。由于统一的协议，它
们可以互相听懂对方的话，可以很方便地与其它物体交流以获取必要的信息，这样省去了很
多麻烦。并且物联网模块也将会提供互联网访问的功能，方便物体获取信息。关于详细的说
明如何获取信息，怎么知道其他物体提供什么信息，以后的文章将会谈到。&lt;/p&gt;
&lt;p&gt;现在这个会说话的物体想去很多物体讲话，那么像人一样，它们也要组成一张关系网络，以
方便的互相交流信息。关系网络分为公有关系网络与私有关系网络。在公有关系网络中，应
为接入这个网络的物体都遵循一个公共的口令（口令这个东西，以后的文章见），物体可以
很广泛的互相交流信息。因为公有关系网络接入不需要像私有网络一样需要严格安全检查以
及没有使用以私有密码加密的数据包，可以看出公有网络的接入是非常方便的，所以公有网
络将会变得很大，拥有公共服务功能的物体一般会接入这个网络，像什么红绿灯，自动气象
台，公共服务机器人，公交车等等，所以物体可以获取的信息种类就非常多。比如说，我公
共汽车站台就可以连入公有网络，通过公用网络很方便地从最近的自动天气站获取天气信
息，在自己的既有功能范围内，调整自己，为旅客提供更舒适环保的等车方案。如果这个公
交站旅客太多又在下雨的话的话，出了为旅客遮风避雨，站台还可以和附近接入公有网络的
手机通信，告诉正在使用手机的人，这个车站人太多，待会再来。当人，使用手机的人也可
以自己住用联系站台获取他们需要的信息。所有的通信都主要是通过无线来完成的，非常便
捷。&lt;/p&gt;
&lt;p&gt;这样，站台就产生了疑问：无线网络的覆盖范围就那么大，我站台怎么和几公里外的人来联
系呢？难道说我装一个大功率发射器不成？其实这是可以的，但是我有一个更好的解决方
案。在我的构想中，一个接入物联网的物体要想有福利，还要承担义务。站台在发出它的信
息的时候，在离他很近的接入物联网的物体都会接到这个消息它们需要负责转发这条信息，
把它传播给其它在它们附近的物体。如果网中物体足够多，消息就可以传达到比较远的地
方。但这种方式不能够解决所有问题，那么为了信息及时传递，在有必要的的情况下，站台
可以直接让物联网模块接入互联网，通过互联网把信息告诉其它物体。其实，在实在没办法
的情况下，比如说处于边缘的地方，物体还可以过有线通信，卫星通信等方式。只是这样的
代价会更大而已。&lt;/p&gt;
&lt;p&gt;这样可以说，物联网的通信方式是非常灵活的，有能力将获取的信息及时传达。还有的是，
公有网络中的每一个物体都有自己的唯一代号，出生的时候就规定好了，这样在公有网络中
的物体就可以定位查找某一样的物体了。除了自己的唯一的代号，物体拥有一个标识叫功能
标识。为什么要有这个标识呢？因为别的物体在与这个物体交流的时候，需要知道这个物体
是干什么的。 来一个综合的例子吧。比如一个人家一个新买的可以说话（接入了物联网）
的电饭煲，人生地不熟，想知道我旁边的物体都可以干什么。我就可以让它们亮出自己的功
能标识，然后这个电饭煲知道自己旁边的仁兄是一个插座，另一位是一个冰箱。显然，电饭
煲对冰箱很感兴趣。由于知道他是电冰箱，电饭煲就可以用本行话与冰箱说话了。他从冰箱
那里获得了冰箱里储存的食物，以及他们的新鲜程度，价格等。它查找了工程师告诉自己的
上网的方法，然后告诉物联网模块用互联网查找一下用这些冰箱里的东西可以做什么。&lt;/p&gt;
&lt;p&gt;互联网告诉他，排骨瘦肉粥，红米粥，绿豆粥（现在的我好饿啊）都不错。那么他再去问问
自己，主人一般喜欢吃啥，从主人手机里知道主人是个江西人，问问互联网，江西人喜欢吃
什么。大数据，以及他自己的直觉（人工智能），告诉他，排骨瘦肉粥不错。那么他告诉主
人的手机（用过功能标识知道的），向主人推荐排骨瘦肉粥作为明天的早餐。十分钟后，主
人通过手机批准了它的推荐。他就在适当的时候，告诉家里的机器人，把冰箱里的原料拿出
来处理好，通过洗菜机洗菜，淘米机淘米，剁肉机剁肉,机器人大厨亲自下厨，经过它们的
共同努力排骨瘦肉粥就做好了。等呈上餐桌，主人吃完。电饭煲第一天的任务就算结束了。
这一趟下来他认识了许多伙伴，这都要归功于物联网。&lt;/p&gt;
&lt;p&gt;当然，以上这些物体交流的信息如果都是通过公有关系网络来的话，就等于把自己家里的信
息公开了。这当然是不允许的，所以我们就有了私有关系网络，来保护我们使用者的隐私与
安全。先写到这里了，下一篇文章将详细介绍私有关系网络的运作原理。 （ps：打字好
累，如果脑子里的东西可以直接变为文本多好，憋着实在难受）&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于物联网形式的思考（一）</title>
      <link>https://blog.bktus.com/archives/02ziks/</link>
      <pubDate>Sun, 16 Oct 2016 11:38:04 +0800</pubDate>
      <guid>https://blog.bktus.com/archives/02ziks/</guid>
      <description>&lt;p&gt;最近在学校里学习任务繁重，感觉都没有时间来思考了，这和初中那段时间可以有大块时间
想与学习无关的事情不同了，毕竟高二了，也要为学习想想了。&lt;/p&gt;
&lt;p&gt;但是，即使是在这样时间紧的情况下，我还是忍不住花些时间来思考。思考的内容就是今天
我在这篇文章探讨的东西。物联网，这个正在不断发展的东西，在未来将会使人类社会的信
息化程度不断提升。但现在，我认为，国内物联网还不成熟，一是没有统一的协议，二是物
联网的概念在国内并不深刻。什么是物联网？先看看维基百科的定义：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;物联网（英语：Internet of Things，缩写 IoT）是互联网、传统电信网等資訊承载体，
让所有能行使独立功能的普通物體实现互联互通的网络。[1]&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;关键的是，所有可以行使独立功能的物体互联互通。这就说明，在物联网这张网上，所有接
入这个网络的物体都可以实现互联互通，互相交流信息，然后运用自己本身自带的功能加上
通过物联网获取的信息使运作更加便捷、快速。在此之前，我第一个想到的是智能家居。智
能家居，通过在开关，门锁上加入通信装置以及必要的功能装置，然后通过手机连接无线主
机对这些只能家居进行控制。在这种模式下，为了安全，所有的通信都必须通过类似无线主
机这样的装置来操作。我在淘宝上看了一下，这种系统以及有很多卖家在卖了。包括小米
等，都已经在这方面探索了。但我认为，这样的思维其实是将物联网的中心化了。&lt;/p&gt;
&lt;p&gt;中心化自然有中心化的好处，也有它的弊端。好处就是，通过无线主机来操控的原理比较简
单，只要把手机连接 wifi 的那一套搬过来就可以了。而且相对来说也比较安全。但是，思
考一下，如果黑客把家里的无线主机攻破了，那么他是不是就等于操纵了你的家里所有的智
能家居？你的所有个人信息黑客都将一览无余。而且这样做的话，物联网这张网的大小就要
被限制了。如果互联网有中心，那么互联网还会达到今天的发达程度吗？显然，物联网要快
速发展，去中心化应该是趋势。去中心化后，两个遵循统一协议的物体之间将可以交流信
息。而且每一个物体的加入，都可以拓展这张网，如同 TCP／IP 协议一样，每一个物体既
可发送信息，接受信息也可以传递信息。我们所要做的就是，将这张网更好得与互联网连接
起来，将它与互联网融合，成为互联网的新的终端。如果能这样做，那么人类的信息获取能
力，传播能力将会大大提高。这样，全人类都可以分享关于这个世界的信息。在这样的情况
下，每个有特定功能的物体就好像获得了智慧一样，他们可以先获取足够的信息，再来进行
更好操作。它们可以互相分享信息，然后更好的服务人类。工程师可以通过这张网，来对它
们的智慧进行改进更新，减少物品换代速率。这样物联网的适用情况就不局限于智能家居等
情况了，随着物品的智能化程度的拓展，物联网会将触角伸向各个角落。在这张网下，每一
个物品不仅仅可以帮助人类完成它们既定的功能，它们还是互联网信息的贡献者，它们会将
它们知道的信息在许可的情况下贡献给互联网，贡献给人类社会。这样的物联网形式将会大
大提升人类社会的信息程度，，信息获取交流将会大大加快，生活会更加便捷。这是物联网
发展的趋势。但不可回避的是，它会带来隐私问题，协议问题，以及安全问题，但这种问题
是可以预防的，在接下来的几篇文章中我将会讨论这些问题。&lt;/p&gt;
&lt;p&gt;注：这篇文章是在匆忙之下完成的，有些遗漏，日后我会完善这篇文章。如果有错误请指
出，谢谢。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
