Zeka 的记事本

2021 年 4 月
« 上个月
1 / 6
关于联想笔记本安装 Linux 无法识别磁盘问题的解释
2021421 日说: Linux

随着 Linux 驱动的更新,信息可能会过时。 使用型号为联想 Y9000X(2020),16G 4K 版本。 参考的解释,可以看 知乎上的回答

在最开始的时候,不论是 Ubuntu 还是 Arch,在进入启动盘后,都无法发现磁盘。当时作为萌新自然是不懂的,看着网上的教程将 raid 模式改为 ahci 模式就解决了。

现在重新回顾这个问题,发现原因很简单,那就是 Linux 缺少针对英特尔的 raid 驱动。Linux 自然是有 raid 驱动的,而且远比 Windows 系统广泛(服务器)。但是为什么到这里就拉跨了呢?原因是此 raid 为英特尔推出的 rst 技术。

rst 黑科技

英特尔的 rst 技术是从软件上实现的,被称为软 raid,这种 raid 理论性能会比硬件组合的 raid 要弱,但是好处是可以非常方便(几乎没有成本)的开启 raid 模式。对于垃圾佬来说,这可是大名鼎鼎的傲腾(Optane)内存技术,使用他就可以将机械盘获得媲美固态的速度。很可惜官方似乎直接 表示了 Linux 不支持

也许几百年后 Wintel 这个牢不可破的联盟解体的时候,Intel 才会突然记起有个系统叫做 Linux 吧。

修改不会出现问题

那么问题就很明白了,我们数据都在一个磁盘上,而不是真正 raid 模式分散在各个磁盘上。所以可以直接修改控制器模式,而理论上不会影响我们的 Windows。照着教程将磁盘格式修改为 ahci 就能在不影响 Windows 的情况下按照完成了。

对于我们的本子,这没有问题。但是对于部分高端笔记本使用了双固态组 raid(有点害怕),要修改格式恐怕只能格式化了。

为什么 raid 模式就不行

但是还有一个问题, 咱们的本子只有 nvme 的 m.2 接口,通信上司是 PCIe。修改的 ahci 只作用于 SATA 协议。为什么修改 SATA 这个与固态似乎没有关系的设置会有效呢?我们的 Linux 用到的不会是 ahci 驱动的固态吧?

回答是放心,通过 lsblk 指令我们看到的是货真价实的 nvme 协议磁盘,并没有经过 ahci。

我们的磁盘是 nvme 驱动的,所以根本不会经过 ahci 协议,在设备管理器上检查也能发现固态是直接挂载在 NVME 控制器上的。所以修改 ahci 是直接绕过去了。

但是开启 rst 就不一样了,rst 是同时软件与硬件合作(iu 集成了相关控件,所以反过来说,au 就不会有这个问题),linux 无法调用 iu 的 rst 相关模块,自然无法读取到磁盘。

ahci 模式下,由于没有 rst 干扰,所以 Linux 直接使用 nvme 相关驱动去识别磁盘,这个过程就不与 ahci 有关系了。

raid 与 ahci 模式性能区别不大

测试 表明两种模式性能差别不大。当然这篇文章发布在 17 年,现在几年过去,虽然不排除有做特殊优化,但是对 Linux 系统来说,是基本享受不到这种好事的。

当然对折腾傲腾内存的垃圾佬来说就不一定了。

厂商默认开启 raid 模式

厂商是默认开启 raid 模式的。

那么问题来了,既然只有一块磁盘,而绝大多数笔记本都不会组 raid(m.2 接口数量本来就不够用,笔记本看重的是轻便性而不是可靠性),两者性能都一样,为何要默认开启 raid 呢?在上面的知乎回答似乎提是厂商与某牙膏厂 py 的结果,是为了防止安装 Linux。这篇文章 甚至提到了因为 rst 导致硬盘本身的管理系统失效,甚至出错等问题。

所以也许只有厂商才能解释清楚了。

所以对于咱们这个本子来说,将格式从 raid 修改为 ahci 是没问题的(在正确操作下),这也解释了为什么 Linux 无法识别到我们的固态。

油猴脚本提前注入脚本
2021415 日说: 前端

之前看到这个 脚本 有点意思,但是美中不足是打开页面图片不会直接替换,而是需要闪烁一下。这已经很影响用户体验了。

为此我重写了一份脚本,发布在 这里

脚本作用很简单,但是使用了一点技巧才最终去掉了闪烁问题。

首先要弄懂为什么要闪烁。如果翻阅 API 文档,就会发现油猴脚本默认执行时间为 document-idle,也就是在文档树解析完成,解释引擎空闲的时候才注入执行。这个默认值是合理的,因为现代应用大多都使用大量的 js 操作 DOM(尤其是 Vue,React 等框架),等待解析完成之后执行不会出现 DOM 未找到的问题。

所以闪烁原因出在这里了。如果要在解析完成之后才注入脚本,那么我们的执行是延迟的。所以为了能尽早注入,我们至少需要添加:

// @run-at document-start

通过这个脚本能告知油猴脚本尽快注入,然后一系列问题出现了。在这个脚本中,出现的主要问题是找不到 DOM 节点。

这个问题有几种产生原因。

浏览器边下载文档边解析

稍微了解 浏览器工作原理就知道当浏览器是边下载 document 边解析的,所以很有可能脚本在注入的时候 DOM 甚至不完全(此处存疑,没有具体考证),这种情况是无法拿到后面 DOM 的。当然这种情况往往只有解析大量 DOM 结点,而你希望操作很后面结点的时候才会发生。

遇到这种情况,我们期望能在 document 准备完毕之后再次尝试,最简单的可以通过事件 DOMContentLoaded。一个可行的 demo 大概是这样的:

// 直接获取结点,不一定能用,使用 try 捕获异常
const nodeNotYetReady = document.querySelector('#id');
try {
    nodeNotYetReady.doSomeMethod();
} catch (_) {
    window.addEventListener('DOMContentLoaded', () => { 
      // 结点应该 OK,可以使用了
      const nodeReadyWithDOM = document.querySelector('#id');
      nodeReadyWithDOM.doSomeMethod();
 })
}

动态渲染

如果通过 JS 动态渲染,那么在 JS 代码没有执行完毕的时候是无法拿到节点的。 以 Google 首页 为例,由于 Google 有 doodles 项目,所以首页 logo 会不断改变,这似乎是通过操作 DOM 实现的。

我们需要知道什么时候 Google 的图片已经准备好了,有两种方式,即轮询与订阅。订阅用到的是 MutationObserver 接口,不论性能还是速率(因为这个事件实际上会被归类到微任务,能保证快速执行)都比较好。文档可以看 这里

但是为了方便,还是做个简单的轮询吧(注意事件尽量简单,这样可以减少 CPU 开销)。

const doSomething = () => {
  try {
    // 执行代码
  } catch (e) {
    // 触发最短延迟重试,可以添加 flag 控制重试次数,防止爆栈
    setTimeout(doSomething);
  } 
};

还有一个问题是原脚本是每次即使发送请求的,所以网络 IO 导致了闪烁。这个的解决方式为将百度的 logo 转化为 base64,然后硬编码到脚本中(调用 localstorage 也许会有额外 io 消耗?)。通过上述执行,效果不错,至少都没有闪烁了。

« 上个月
1 / 6
0%