点滴技术分享

徐小东

2022-12-05

Linux/Unix 的 9 条设计哲学

{出处1 《Linux/Unix 设计思想》 — Mike Gancarz}

核心思想:KISS (Keep it simple, stupid)2 https://en.wikipedia.org/wiki/KISS_principle

  1. 准则 1 小即是美
  2. 准则 2 让每个程序只做好一件事情
  3. 准则 3 尽快建立原型
  4. 准则 4 舍弃高效率而取可移植性
  5. 准则 5 采用纯文本来储存数据
  6. 准则 6 充分利用软件的杠杆效应
  7. 准则 7 使用 shell 脚本来提高杠杆效应和可移植性
  8. 准则 8 避免强制性的用户界面
  9. 准则 9 让每一个程序都成为过滤器

deepin 是怎么诞生的

1997 deepin 发起创立了 WHLUG(武汉 Linux 用户组)

2004 Hiweed Linux 发布

2008 deepin 收购 Hiweed Linux 团队和品牌,建设 deepin 社区

2009 更名为 Linux Deepin,发布 9.12 版本

2011 deepin 开发团队成立武汉深之度科技有限公司

2014 名称最终改为 deepin

2015 deepin v15 发布

2020 deepin v20 发布

Zettelkasten 卡片盒笔记法

Zettelkasten3 https://en.wikipedia.org/wiki/Zettelkasten 为德语,翻译为英文为 slip box,亦即卡片盒。

发明人:德国社会学家 Niklas Luhmann(尼克拉斯·卢曼)4 https://en.wikipedia.org/wiki/Niklas_Luhmann,毕业后当公务员,业余爱好社会学,依靠此方法成为了大学教授、出版了 70 本专著、400 篇学术文章。

工作方法

将各种来源的想法、内容写在卡片上,放进盒子里,彼此建立连接。

  1. 写临时性的笔记:来自脑中闪过、或书中看到的内容,用完即弃。
  2. 写资料性的笔记:将临时性的笔记转译成自己的文字,尽量精简,只保留最重要的东西。
  3. 写永久性的笔记:该法最核心部分,让知识能长久保存。从整理前两种笔记开始,思考这些笔记跟你当前的写作、研究、兴趣或想法是否有关联之处。完成后将永久性笔记放入主要的盒子,资料性笔记放入资料来源的盒子,并把临时性笔记丢掉。

思维原则

链接

5 种常见的软件架构模式

分层架构

模式描述

  • 也叫 N 层架构,最为常见,大多数应用的架构模式。
  • 组件被分成几个平行的层次,每一层代表应用的一个功能,每一层都有特定的角色和职能。
  • 大多数结构都分成 4 层:展示层、业务层、持久层、数据库层。
  • 分层架构的一个突出特性是组件间关注点分离,一个层中的组件只会处理本层的逻辑。

关键概念

  • 每一层都是封闭的,这是分层架构中非常重要的特点。
  • 层隔离:某一层的改变不会影响其它层。
  • 开放和封闭层的概念确定了架构层和请求流之间的关系。

事件驱动架构

模式描述

  • 一种主流的异步分发事件架构模式,常用于设计高度可扩展的应用。
  • 由高度解耦、单一目的的事件处理组件构成,这些组件负责接收和处理事件。

关键概念

两种主要的拓扑结构:中介(mediator)拓扑和代理(broker)拓扑。

  1. mediator 拓扑:需要在事件内使用一个核心中介分配、协调多个步骤间的关系、执行顺序时使用。
  2. broker 拓扑:不通过一个核心中介将多个事件串联在一起时使用。

注意事项

  • 实现更困难。
  • 不能处理细粒度的事务。

微内核架构

模式描述

  • 也称插件化应用架构,对基于产品的应用程序来说是很自然的选择。
  • 可通过插件的形式添加额外的特性到核心系统中,提供了很好的扩展性,也使新特性和核心系统隔离开。

关键概念

主要考虑两个方面:核心系统和插件模块。

  1. 核心系统一般只包含一个能够使系统运作起来的最小化模块。核心系统需要了解插件模块的可用性以及如何获取到它们,通用的实现方法是通过一组插件注册表。
  2. 插件模块包含专业处理、额外特性的独立组件;通常插件模块之间没有任何依赖。插件模块可以通过多种方式连接到核心系统,包括 OSGi、消息机制、Web 服务或直接点对点的绑定。

插件和核心系统的通信规范包含标准规范和自定义规范。

微服务架构

模式描述

  • 替代单体应用和面向服务架构。
  • 单独部署单元:每个组件都作为一个独立单元进行部署,每个单元通过传输管道进行通信,应用和组件之间高度解耦。
  • 最重要的概念是服务组件,可小到单一的模块,大至一个应用程序。
  • 另一个关键概念是分布式架构,内部的所有组件之间是完全解耦的,并通过某种远程访问协议进行访问。

关键概念

3 种常见拓扑结构:

  1. 基于 REST API:适用于网站,通过 API 对外提供小型的、自包含的服务,如 Google、Amazon。
  2. 基于 REST 的应用:通过传统的基于 Web 或胖客户端业务应用来接收客户端请求。
  3. 集中式消息:使用轻量级的集中式消息代理,如 ActiveMQ、HornetQ,通常应用在较大的业务应用程序中。

云架构

模式描述

专门为了解决伸缩性和并发问题而设计。

关键概念

两个主要模块:处理单元和虚拟化中间件。

  1. 处理单元包含应用模块,即 Web 组件及后台业务逻辑,还包括复制引擎。
  2. 虚拟化中间件负责保护自身以及通信。
5 种软件架构模式比较

5 种软件架构模式比较

4 个基本的设计原则

{出处11 《写给大家看的设计书》 — Robin Williams}

亲密性(Proximity)

相近的元素以视觉单元的形式出现。

对齐(Alignment)

每种要有视觉上的联系。

重复(Repetition)

视觉元素要重复出现。

对比(Contrast)

即要避免页面上的元素太过相似。

应用设计原则前

应用设计原则前
应用设计原则后

应用设计原则后

战胜遗忘、高效学习的间隔重复法

赫尔曼·艾宾浩斯遗忘曲线

遗忘曲线

遗忘曲线

间隔重复法

间隔重复软件

参考

R Markdown:动态生成文档利器

Markdown

一种轻量级标记语言,由约翰·格鲁伯创建。20 https://en.wikipedia.org/wiki/Markdown允许人们使用易读易写的纯文本格式编写文档,然后转换成 HTML。

R

主要用于统计分析、绘图以及数据挖掘的编程语言。21 https://en.wikipedia.org/wiki/R_(programming_language)

R Markdown

两大特点:

  1. 能直接嵌入代码,并予以执行,如:R、Python、Shell、C、Go、SQL 等等,可实现计算机大师高德纳所提出的文学式编程(literate programming)。
  2. 支持输出许多文档格式,包括:HTML、PDF、Word、ePub、简历、网站、幻灯片、电子答卷、书籍等等。

安装

方法一:

  1. 安装 R:$ sudo apt install r-base
  2. 启动 R:$ R
  3. 安装 rmarkdown:install.packages("rmarkdown")

方法二:

  1. 拉取镜像:$ docker pull toyland/bookdown
  2. 运行容器:$ docker run --rm -v $PWD:/work toyland/bookdown

样例:制作幻灯片

---
title: "R Markdown:动态生成文档利器"
author: "徐小东"
date: "2022-12-05"
header-includes:
  - \usepackage{ctex}
output:
  beamer_presentation:
    theme: default
    latex_engine: xelatex
---

## Markdown

一种轻量级标记语言,由约翰·格鲁伯创建。

---(snip)---

样例:剖析

渲染文档

$ Rscript -e 'rmarkdown::render("rmd.Rmd", "all")'

输出为 rmd.pdf

代码块

```{bash}
ls *.Rmd
```
ls *.Rmd
## arch-share.Rmd
## book-guide.Rmd
## encrypted-squashfs.Rmd
## fapolicyd.Rmd
## font-render.Rmd
## ide-solution.Rmd
## ide-tech.Rmd
## ide.Rmd
## initrd.Rmd
## linux-dm.Rmd
## oemid.Rmd
## oemid_old.Rmd
## oemscan.Rmd
## pipewire.Rmd
## rmd.Rmd
## time-man.Rmd
## wm.Rmd

表格

knitr::kable(iris[1:5, ], caption = 'A caption')

A caption

Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa
4.6 3.1 1.5 0.2 setosa
5.0 3.6 1.4 0.2 setosa

图形

#plot(cars, pch = 18)

参考

Linux 桌面的窗口管理方法学

何为 WM

WM 即 window manager,亦即窗口管理器,它主要用于控制窗口的布局和外观。一般来说,WM 是桌面环境的一部分,但它也可以独立使用。

两种管理方法

  1. Stacking(堆叠式),也叫 floating(浮动式),顾名思义,不同窗口可以相互重叠,就像桌子上随意摆放的白纸一样。比如,Windows 和 macOS 皆属此法。
堆叠式

堆叠式

  1. Tiling(平铺式),即窗口不能够重叠,而是像瓦片一样挨个摆放。
平铺式

平铺式

主要的区别

二者的主要区别如下:

类型 布局 内容 改变行为
堆叠式 特定顺序(层) 会重叠 鼠标
平铺式 水平/垂直平铺 不会重叠 键盘

平铺式相比堆叠式的窗口管理方法具有下列优点:

使用多显示器

使用多显示器

平铺式窗口管理器的代表

Linux 音频栈

ALSA

ALSA28 https://alsa-project.org/ 是 Advanced Linux Sound Architecture 的简称,它主要包含两部分:

  1. 在内核态,作为内核的音频子系统,提供声卡驱动
  2. 在用户态,提供库(libasound,API)和命令行工具(alsamixer、aplay、arecord 等)

PulseAudio

PulseAudio29 https://www.freedesktop.org/wiki/Software/PulseAudio/ 是一个具备网络能力的声音服务器,它作为接口引擎介于应用程序和 ALSA 之间。

Linux API

Linux API

PulseAudio 的后台 daemon 从一个或多个源(进程、捕捉设备等)接收声音输入,然后将这些声音源重定向到 sinks(声卡、远端 PulseAudio 服务器、其它进程)。

PulseAudio 主要包括以下部分:

JACK

JACK30 https://jackaudio.org/ 是 JACK Audio Connection Kit 的简称,它是一个专业级的声音服务器,在音频和 MIDI 数据间提供实时、低延迟的连接。从 2002 年起,JACK 是 Linux 上专业音频软件的关键基础架构和默认标准。

JACK 包括:

PipeWire

简介

PipeWire31 https://pipewire.org 由 Wim Taymans(Red Hat 工程师,同时也是 GStreamer 的创建者)所开发,它是 Linux 上用于处理音频及视频流的服务器。PipeWire 提供统一的框架访问多媒体设备,而上层应用则通过 PipeWire 的 API 来使用硬件,其主要特点包括:

  • 用最低延迟捕获及播放音频和视频
  • 针对音频和视频的实时多媒体处理
  • 多进程架构允许应用程序共享多媒体内容
  • 无缝支持 PulseAudio、JACK、ALSA 及 GStreamer 应用程序
  • 对沙盒应用(如 Flatpak)提供支持
The multimedia stack

The multimedia stack

PipeWire

PipeWire

PipeWire 主要包括:

  • PipeWire 后台 deamon
  • Session Manager:会话管理器,管理 PipeWire deamon 中的对象
  • PipeWire 工具:跟 daemon 交互
  • libpipewire 库:开发应用及插件
  • pipewire-pulse:兼容 PulseAudio
  • libjack:兼容 JACK
  • gstreamer-pipewire:兼容 GStreamer
  • 插件:alsa、ffmpeg、v4l2、bluez5 等

场景

  • PulseAudio 及 JACK(专业级音频)替代(吸收 CoreAudio、AudioFlinger 的想法)
  • 视频捕捉服务器(摄像头、其它视频源),屏幕共享(Firefox、Chromium、OBS Studio)

优势

针对桌面及专业级音频使用场景提供统一的音频基础架构,终结碎片化的音频现状。

  • 专业级音频特性:专业级音频应用程序倾向于使用 JACK API 和 JACK daemon,既难设置,集成又差。利用替代的 libjack 库,专业级音频应用程序可直接运行在 PipeWire 上。
  • 灵活性/集成:PipeWire 设计为多进程,使其可更好的与其它系统组件集成。
  • 性能:PipeWire 被设计为高性能、低延迟。
    • 零拷贝:利用现代 Linux kernel API(memfd、dmabuf)
    • 比 PulseAudio 更低的 CPU 占用
    • 更低功耗,设备不用时能进入休眠,eventfd 唤醒进程
  • 安全:强调客户端安全,可独立配置客户端的对象可见性及操作。更好的支持沙盒程序的策略。
  • 可维护性:PulseAudio 和 JACK 都是很慢的开发周期,PipeWire 灵活的设计可支撑更多新特性交付。

PipeWire 采用 MIT 许可授权。

采用

  • Fedora 从 34 起交付 PipeWire,用以替换 PulseAudio。
  • Arch Linux 已默认采用 PipeWire 取代 PulseAudio。
  • GNOME 及 Arch Linux 社区对 PipeWire 赞誉有加32 https://en.wikipedia.org/wiki/PipeWire,它修复了许多原本属于 PulseAudio 的问题,如:高 CPU 占用、蓝牙连接问题、JACK 后端问题等。

Linux 显示管理器

显示管理器的英文全称为 display manager,也叫 X display manager,意指在 X 服务器上启动登录会话的图形化登录管理器。

职责

文本模式登录

  1. 启动 login 程序
  2. 获取帐号及密码
  3. 检查 /etc/passwd 看帐号是否存在
  4. 检查 /etc/shadow 看密码是否匹配
  5. login 程序 fork 子进程创建登录 shell
文本模式登录过程

文本模式登录过程

实现

图形模式登录

  1. 启动显示服务器(如 X11)并运行 Greeter
  2. 传递帐号及密码给 PAM(pluggable authentication module)进行认证
  3. Greeter 启动会话

Linux 上字体工作原理

计算机字体

是包含有一套字形与字符的电子数据文件,常分为:

TTY 中的字体

图形化系统中的字体

FreeType(Font engine,字体引擎)

用来将字符栅格化并映射成位图以及提供其他字体相关业务的支持,它提供了一个简单、易用并统一的接口来访问字体文件的内容。37 https://www.freetype.org

  • 1996 年由大卫·特纳(David Turner)开发
  • 支持 TrueType、Type 1、OpenType 等字体格式
  • 字体微调(Hinting)
  • 抗锯齿
  • 次像素渲染

HarfBuzz(Layout engine,排版引擎)

用于文字塑形的软件开发库,亦即用于转换 Unicode 文本到字形指标及方位的过程。38 https://github.com/harfbuzz/harfbuzz

  • 原为 FreeType 的一部分
  • 由贝赫达德·埃斯法赫博德(Behdad Esfahbod)所开发
  • 常用 UI 库及应用(Firefox、Chromium、Inkscape 等)以它为基础

Fontconfig(字体配置)

用于配置、定制全系统的字体,或将字体提供给应用程序使用。39 https://www.freedesktop.org/wiki/Software/fontconfig/

  • 最初是由基思·帕卡德(Keith Packard)开发
  • 支持查询和模式匹配来获得字体
  • 配置文件采用 XML 格式(/etc/fonts
  • 提供命令行工具来管理字体配置:fc-listfc-matchfc-cache

Linux 图形栈

概览

内核空间

  • DRM
  • KMS

用户空间

  • libdrm
  • Mesa
  • 显示服务器驱动(X11)
Linux 图形栈

Linux 图形栈

DRI 与 DRM

DRI40 https://dri.freedesktop.org/ 即 Direct Rendering Infrastructure,在 X11 下以安全、高效的方式直接访问图形硬件的框架。DRI 实现分散在 X 服务器及其相关的客户端库、Mesa 和 DRM 内核子系统中。

DRM41 https://dri.freedesktop.org/wiki/DRM/ 即 Direct Rendering Manager,Linux 内核中负责显卡 GPU 的接口子系统。DRM 暴露 API,用户空间程序可以使用它向 GPU 发送命令和数据,并执行一些操作,比如配置显示器的模式设置。用户空间程序可以使用 DRM API 命令 GPU 进行 3D 硬件加速渲染和视频解码,以及 GPGPU 计算。

KMS

KMS 即 kernel mode-setting,激活计算机显示控制器的显示模式(屏幕分辨率、颜色深度和刷新率)。

libdrm

DRM 的用户空间库,便于用户空间程序与 DRM 子系统交互。

Mesa

也叫 Mesa3D42 https://mesa3d.org/,OpenGL、Vulkan 和其他图形 API 规范的开源软件实现。Mesa 将这些规范转换为特定于供应商的图形硬件驱动程序。除了游戏等 3D 应用程序,现代化显示服务器使用 OpenGL/EGL。因此,所有图形通常都经过 Mesa。

显示服务器驱动(X11)

主要分为两部分:

Org Mode:敏捷有效的纯文本系统

Org-mode 与 GNU Emacs

GNU Emacs43 https://www.gnu.org/software/emacs/:可扩展、可定制、完全自由的文本编辑器。

Org-mode44 https://orgmode.org/:适用于 GNU Emacs 的文本编辑模式,由 Carsten Dominik 在 2003 年开发,常用于:

很多人用它管理自己的整个数字生活。

Org-mode 的移植

随着 Org-mode 的成功及流行,它已被移植到其他编辑器,如:

Org-mode for 移动设备

Org-mode 的特点

Org-mode 示例

Org mode 示例

Org mode 示例

Org mode 表格

Org mode 表格

Org mode 计划

Org mode 计划

Linux Kernel 概览

Kernel 的任务

内核是硬件与软件之间的一个中间层。作用是将应用程序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址。

Kernel 架构类型

Kernel 架构类型

Kernel 架构类型

Linux kernel 简介

Linux kernel 是自由开源、单体、模块化、多任务、类 Unix 的操作系统内核。

Linux kernel 代码行数

Linux kernel 代码行数

Linux Kernel 的组成部分

Kernel 的组成部分

Kernel 的组成部分

进程管理和调度

问题

  1. 如何共享 CPU 时间:内核必须决定为各个进程分配多长时间
  2. 如何在进程之间切换:何时切换到下一个进程,哪个进程是下一个

这两个任务是称之为调度器的内核子系统的职责。

解决方案

抢占式多任务处理(preemptive multitasking),各个进程都分配到一定的时间段执行,但重要的进程会比次要的得到更多的 CPU 时间。

进程执行模型

  • fork:生成当前进程的一个相同副本,该副本称之为子进程。原进程的所有资源都以适当的方式复制到子进程。
  • exec:从一个可执行的二进制文件加载另一个应用程序,来代替当前运行的进程。

进程生命周期

  • 运行:该进程此刻正在执行。
  • 等待:进程能够运行,但没有得到许可,因为 CPU 分配给另一个进程。
  • 睡眠:进程正在睡眠无法运行,因为它在等待一个外部事件。
  • 终止:进程关闭。
  • 僵尸:这样的进程已经死亡,但仍然以某种方式活着。

进程优先级

  • 硬实时进程:具有严格的时间限制,某些任务必须在指定的时限内完成。硬实时进程的关键特征是,它们必须在可保证的时间范围内得到处理。例子:RTLinux
  • 软实时进程:硬实时进程的一种弱化形式,写入进程在需要CPU时间时应该能够得到保证,至少优先于所有其他普通进程。
  • 普通进程:没有特定时间约束,但仍然可以根据重要性来分配优先级。

进程调度器

  • O(1) 调度器:在 Linux 2.6 引入,根据经典的时间片分配的思路来进行整体设计,它可以在常数时间内完成其工作,不依赖于系统上运行的进程数目。时间片的思路就是将 CPU 的执行时间分成一小段一小段的,假如是 5ms 一段。于是多个进程如果要“同时”执行,实际上就是每个进程轮流占用 5ms 的 CPU 时间,而从 1s 的时间尺度上看,这些进程就是在“同时”执行。当然,对于多核系统来说,就是把每个核心都这样做就行了。
  • 完全公平调度器(completely fair scheduler),在内核版本 2.6.23 开发期间合并进来,它试图尽可能地模仿理想情况下的公平调度。如果当前有 n 个进程需要调度执行,那么调度器应该在一个比较小的时间范围内,把这 n 个进程全都调度执行一遍,并且它们平分 CPU 时间,这样就可以做到所有进程的公平调度。
CFS 调度器

CFS 调度器

所有的可运行进程都按时间在一个红黑树中排序,所谓时间即其等待时间。等待 CPU 时间最长的进程是最左侧的项,调度器下一次会考虑该进程。等待时间稍短的进程在该树上从左至右排序。

内存管理

从进程的角度来看,Linux 将虚拟地址空间划分为两个部分,分别称为内核空间和用户空间。

虚拟地址空间

虚拟地址空间

大多数情况下,单个虚拟地址空间就比系统中可用的物理内存要大。内核和 CPU 必须考虑如何将实际可用的物理内存映射到虚拟地址空间的区域。

虚拟和物理地址

虚拟和物理地址

可取的方法是用页表来为物理地址分配虚拟地址。虚拟地址关系到进程的用户空间和内核空间,而物理地址则用来寻址实际可用的内存。

分配虚拟地址

分配虚拟地址

多级分页:为减少页表的大小并容许忽略不需要的区域,计算机体系结构的设计会将虚拟地址划分为多个部分。

伙伴系统

伙伴系统

伙伴系统:快速检测内存中的连续区域,供内核分配连续页。

slab 分配器

slab 分配器

slab 缓存:分配比页帧小的内存块,并缓存频繁使用的小对象。

I/O

内核必须处理 3 方面的问题:

  1. 必须根据具体的设备类型和模型,使用各种方法对硬件寻址。
  2. 内核必须向用户应用程序和系统工具提供访问各种设备的方法。
  3. 用户空间需要知道内核中有哪些设备可用。
外设寻址的分层模型

外设寻址的分层模型

内核与外设通信的方法:

设备文件:用于访问扩展设备,这些文件建立了与某个设备驱动程序的连接,以支持与扩展设备的通信。

I/O 调度:内核采用的各种用于调度和重排 I/O 操作的算法,称之为 I/O 调度器。

虚拟文件系统:为支持各种本机文件系统,且同时允许访问其他操作系统的文件,Linux 内核在用户进程(或 C 标准库)和文件系统实现之间引入了一个抽象层。该抽象层称之为虚拟文件系统(Virtual File System),简称 VFS。

Ext 文件系统族:Ext2/3/4

硬盘上的启动扇区和块组

硬盘上的启动扇区和块组

每个文件系统都由大量块组组成,在硬盘上相继排布。

Ext2 文件系统的块组

Ext2 文件系统的块组

块组是 Ext2 文件系统的核心要素。

Ext3:提供了一种日志(journal)特性,记录了对文件系统数据所进行的操作。在发生系统崩溃之后,该机制有助于缩短 fsck 的运行时间。

Ext4:大型文件系统(单文件最大支持 16 TiB,卷最大支持 1 EiB)、持久预分配、日志校验和、透明加密等。

网络

问题

从程序员的视角来看,程序如何访问网络功能?

解决方案

网卡的运作方式与普通的块设备和字符设备完全不同,使得经典的 UNIX 箴言“万物皆文件”不再完全适用。

将一种称为套接字的特殊结构用作到网络实现的接口,这种方案现在已经成为工业标准。

内核中分层模型的实现

内核中分层模型的实现

内核网络子系统的实现与 TCP/IP 参考模型非常相似。

系统调用

系统调用用于从用户应用程序调用内核例程,以利用内核的一些专门的功能。

谈谈 GIO

GTK

用来创建 GUI 的跨平台 widget 工具包。其架构如图所示:

GTK 架构

GTK 架构

GLib

由 GNOME 维护,用 C 编写的低级系统库。开始为 GTK 的一部分,后从非 GUI 部分剥离而成。它包含下列组件:

GIO

简介

  • 即 Gnome Input/Output 的简称,提供现代、易用的 VFS 接口库。它允许应用程序使用统一的 API 来访问本地及远端文件,此外具有网络和 D-Bus 支持。
  • 设计目标:一方面是克服 GnomeVFS 的缺点,如:无 Display Names 概念、不支持图标、身份验证框架有问题等。另一方面,替代原始的 POSIX 调用。
  • 定位:作为 GNOME Shell/GNOME/GTK 软件栈的低级系统库,独立维护 libgio-2.0 ,但与 GLib 一起打包。
  • 开发语言: C
  • 开源协议:GNU LGPL 2.0 及更新版

特性

  • I/O、文件的接口和基类
  • stream 类
  • 文件类型处理
  • 存储、检索应用设置
  • 文件监视 inotify 和 FAM
  • 异步 I/O
  • 支持网络编程,域名解析、低级 socket API、高级客户端/服务器辅助类
  • 支持连接到 D-Bus

GVfs

GIO 与 GVfs

GIO 与 GVfs

  • GVfs 即 GNOME Virtual file system,针对 GIO 设计的 GNOME 用户态虚拟文件系统,作为 GIO 的可载入模块,扩展 GIO。
  • 也有 FUSE 支持,用于不用 GIO 的应用程序,但功能有限。
  • 挂载后端
    • FTP/SFTP
    • SMB
    • WebDAV
    • MTP
    • 本地数据 (通过 Udev)
  • 卷监视器及持久元数据存储
  • 组件
    • gvfsd: 后台 daemon,管理器及消息路由,由 GIO 客户端启动
    • gvfsd-fuse: FUSE daemon,由 gvfsd 启动
    • gvfsd-metadata: 元数据存储,由 GIO 客户端启动
    • gvfs-*-volume-monitor: 卷监视器
    • gvfsd-{sftp,smb,http}: mount 后端
    • gio: GIO 命令行工具

客户端 Nautilus

  • 依赖 GVfs 来浏览本机和远端文件系统。
  • 使用 GIO 库实时跟踪本机文件的修改。
  • 依赖 Tracker 索引文件,能提供快速的文件搜索结果。

参考

initrd 详解

是什么

initial ramdisk,它是一种将临时的根文件系统载入内存的方案,主要用于 Linux 的启动过程。也叫 early user space (早期用户空间),在 Linux kernel 2.5.46 引入。从出现至今存在以下两种方案:

initrd 在 Linux 引导过程中的作用

initrd 在 Linux 引导过程中的作用

存在原因

从根本上说:

其他次要的因素:

具体实现

制作工具

手动创建

mkdir --parents /usr/src/initramfs/{bin,dev,etc,lib,lib64,mnt/root,proc,root,sbin,sys}
cp --archive /dev/{null,console,tty,sda1} /usr/src/initramfs/dev/ # 设备节点
#!/bin/busybox sh

# Mount the /proc and /sys filesystems.
mount -t proc none /proc
mount -t sysfs none /sys

# Do your stuff here.
echo "This script just mounts and boots the rootfs, nothing else!"

# Mount the root filesystem.
mount -o ro /dev/sda1 /mnt/root

# Clean up.
umount /proc
umount /sys

# Boot the real thing.
exec switch_root /mnt/root /sbin/init
find . -print0 | cpio --null --create --verbose --format=newc | gzip --best > /boot/custom-initramfs.cpio.gz

配置 GRUB:

initrd custom-initramfs.cpio.gz # /boot/grub/grub.cfg

参考

Linux 访问控制

问题:因为一个用户可以拥有一个文件,所以他能够读取、写入,甚至删除该文件。那么,对于系统上的其他用户来说,他们被允许做什么?

基础

资源与所有权

资源与所有权

资源与所有权

  • Users:用户启动进程并拥有文件。
  • Files:文件具有所有者,默认为创建该文件的用户,且可供进程使用。
  • Processes:进程使用文件进行通信及持久化数据。

访问控制的类型

  • Discretionary access control (DAC):自主访问控制,基于用户的身份来限制访问资源。
  • Mandatory access control (MAC):强制访问控制,基于表示安全级别的层级模型来限制访问资源。用户被分配许可级别,而资源被分配安全标签。用户只能访问等于或低于许可级别的相应资源。管理员严格并单独控制访问及设置所有权限。例子: SELinux 、AppArmor。

用户

类型

  • 系统用户:程序使用这些用户来运行后台进程。
  • 一般用户:正常的人类,与系统进行交互。

用户 ID (UID)

32 位数字值,Linux 通过 UID 标识用户,用户属于一个或多个组 (GID)。

  • 0:
  • 1~999:保留给系统使用
  • 65534:nobody
  • 1000~65533、65536~4294967294:一般用户

本机管理用户

使用简单的基于文件的接口。

  • 用户数据库: /etc/passwd
用户数据库

用户数据库

  • 组数据库: /etc/group
  • 用户密码: /etc/shadow
  • 组密码: /etc/gshadow

集中管理用户

  • 基于目录: LDAP
  • 通过网络:Kerberos
  • 使用配置管理系统:Ansible、Chef、SaltStack

权限

文件权限

Linux 访问资源的核心概念。

类型或权限范围

  • 用户:文件的所有者。
  • 组:有一个或多个成员。
  • 其他人:别的人落到这个类别。

访问类型

访问类型

访问类型

  • 读取 (r):对于一般文件,允许用户查看文件的内容;对于目录,允许用户查看目录中的文件名称。
  • 写入 (w):对于一般文件,允许用户修改及删除文件;对于目录,允许用户在目录中创建、重命名、删除文件。
  • 执行 (x):对于一般文件,允许用户执行文件(若用户也有读取权限);对于目录,允许用户访问目录中的文件信息,转到目录 ( cd ) 或列出内容 ( ls )。

进程权限

从进程的视角来看,相关的权限是什么。

  • 真实 UID:用户启动进程的 UID,它表示进程的所有权。
  • 生效 UID:当访问共享资源时,Linux 内核使用该 UID 来决定进程的权限。
  • 保存的 set-user ID:用于 suid 场合,通过在真实 UID 和 set-user-ID 之间切换生效 UID 来获得权限。
  • 文件系统 UID:一般而言,跟生效 UID 相同。

高级权限管理

能力

  • 与 root 关联的传统权限分解成可独立分配给每个线程的不同单元。

    CAP_NET_ADMIN :允许各种网络相关操作。

    CAP_SYS_ADMIN :允许系统管理操作。

    CAP_SYS_PTRACE :允许使用 strace 来调试进程。

  • 能力一般仅与系统级任务相关。

  • 查看能力: capsh --print

  • 管理能力: getcapsetcap

seccomp 预置

  • Secure computing mode48 https://en.wikipedia.org/wiki/Seccomp:安全计算模式,其基本想法是使用专门的系统调用 seccomp 来限制进程可用的系统调用。为 Linux 内核提供沙箱能力。
  • 容器场合:Docker、K8s 支持 seccomp。

访问控制列表

调试九法:软硬件错误的排查之道

{作者 David J.Agans50 https://book.douban.com/subject/5376270/}

  1. 理解系统

    理解系统的基本方法就是阅读手册,逐字逐句阅读整个手册,避免跳读,问题的线索可能就隐藏在被略过的那些章节中。知道工作流程,尝试寻找 bug 时,必须知道要查找的路线。了解工具,调试工具是用来观察系统的眼和耳,必须选择正确的工具,正确地使用工具,并正确地解释得到的结果。

  2. 制造失败

    原因是可以观察它,可以专心查找原因,可以判断是否已修复问题。从头开始,引发失败。

  3. 不要想,而要看

    观察失败,一定要亲眼看到实际错误是如何发生的,观察往往比猜测能够更快地找到问题。查看细节,一直观察,直到把问题的原因锁定在几种可能性之内。猜测只是为了确定搜索的重点目标。

  4. 分而治之

    调试的核心。缩小搜索范围,从有问题的支路开始查找问题。

  5. 一次只改一个地方

    使用步枪,而不要用散弹枪。与正常系统进行比较。追问:自从上一次能够正常工作以来你更改了什么?

  6. 保持审计跟踪

    记下你的每步操作、顺序和结果。魔鬼隐藏在细节中,描述事情的时候要具体且一致。

  7. 检查插头

    敢于怀疑自己的假设,从头开始检查。

  8. 获得全新观点

    要想重新理清一个案子的头绪,最好的方法就是把它将给别人听 — 福尔摩斯

    寻求帮助,询问专家,借鉴别人的经验。

  9. 如果你不修复 bug,它将依然存在

    bug 从来不会自己消失,要从根本上解决问题。

PARA 方法:组织数字信息的通用系统

信息组织系统

它能有效的支持你的当下和未来的工作,告诉你信息都被放在了哪里,以及当你需要的时候就能快速找到,并且不会被工具所束缚。

一般信息组织法的问题

别让你的信息变成坟场!

何为 PARA

PARA 方法由个人生产力专家 Tiago Forte51 https://fortelabs.co/about-forte-labs/ 提出,同时他也是《Building a Second Brain》一书的作者。PARA 是以下 4 个单词的首字母缩写:

Project

项目,具有明确目标及时间范围的一系列任务,例如:完成应用原型、开发项目计划、写博文等。

Area

领域,日常需要精进的领域,可以是你的兴趣,也可以是你想建立的习惯、长期目标,例如:产品开发、写作、生产力等。

Resource

资源,感兴趣的题目或主题,支撑领域的外部知识储备,例如:项目管理、习惯养成、在线市场等。

Archive

存档,上述 3 类之外不活动的内容,也许对未来有用,例如:已完成的项目、不再维护的领域、不再感兴趣的资源。

如上图,领域:Product Development,项目:product X launch,任务:write first draft of blog post。任务与项目相关联。项目总是归属于某个领域。

PARA 的优势

PARA 方法为我们提供了一种组织数字信息的思路,其核心是根据数字信息的可操作性程度,对信息进行聚焦或转移。它不是硬性地把信息锁定在某个类目上,而是按信息的使用程度来显示它们目前的状态

PARA 里的信息是可以流动的:

会否付诸实际行动,是 PARA 方法的关键

聚焦项目与领域的关系

项目代表当下,而领域更加关注未来。创建一个清晰的项目清单,能让你知道你的能力边界。而一旦界定了边界,你就可以有意识地、战略性地决定做或者不做,如何弥补还是尽快放弃。

如何开始

  1. 理清你的领域

    理清领域最难的地方在于,你要坦然面对自己的内心。停下来问问自己想要成为什么样的人(而不是别人希望我们成为的人),那么可以把这件事当做一切的起点。

  2. 先定义项目清单

    核心问题是定义你的项目,而工具只是一个解决手段。与其寻找 「一个万能的通用工具」,不如制定你的项目列表,然后将这个列表复制到你现在和将来使用的每一个工具上。

  1. 建立项目清单

    收集完整的清单是获得控制权的第一步。创建一个清晰的项目清单,让你有信心对新的承诺说是或不是。

  2. 和过去告别

    如果从未使用过 PARA 方法,那么可以这样重新开始。不如和过去的信息告别,将它们束之高阁,当需要的时候,通过搜索还是能找到它们。所谓近年流行的讲法“断舍离”。

参考

容器的核心技术

基本概念

Container (容器):使用 Linux namespace (名字空间)、cgroups (控制组)、及 CoW (写时拷贝) 文件系统来提供应用级依赖管理的 Linux 进程组。

使用场景包括本地测试和开发、分布式生产环境,如:Kubernetes。

一般通过容器镜像和人类友好的用户接口这种标准化的方式来定义打包。OCI (Open Container Initiative) 规范定义和分发容器镜像、执行容器。

容器具有 immutability (不可变性)。

Linux 名字空间

Linux 本来有资源的全局视图,为了允许进程有资源的局部视图 (如:文件系统、网络、甚至用户等),于是 Linux 引入了名字空间。

Linux 名字空间是有关资源可见性的内容,且可以用来隔离操作系统资源的不同方面。

创建名字空间的系统调用:

查看名字空间: sudo lsns

Linux 控制组

一种管理进程组的机制,可用来控制系统资源占用,如:CPU、内存、I/O 等。

内核提供两个 cgroups 版本:

cgroups 包含 CPU、内存、I/O、PID、device 等控制器。

写时拷贝文件系统

Copy-on-Write (写时拷贝) 文件系统用来提升 I/O 速度,同时减少使用空间。

原文件 File 1 由 A、B、C 块组成,拷贝的文件叫 File 2。代替拷贝实际的块,只拷贝元数据 (块的指针)。

当 File 2 修改时 (假定 C 块更改),只拷贝 C 块:新的 C’ 块被创建,而 File 2 仍然指向未修改的 A 和 B 块。

union mounts (联合挂载):将多个目录组合 (挂载) 到一个位置,这样,对于最终目录的用户来说,该目录包含所有参与目录的组合内容。

实现包括:

在容器中,CoW 用于构建时,将应用及所有依赖打包成可分发的单一、自包含文件。通常将 CoW 文件系统与绑定挂载结合使用,以一种有效的方式将不同依赖项的内容层放在彼此之上。

参考

Linux 控制台、终端及 Shell

在谈及 Linux 命令行时,有时会遇到控制台、终端、终端模拟器、以及 Shell 这几个基本概念。有些朋友往往傻傻分不清楚,下面就来做个一一介绍。

控制台

控制台(Console),又称为系统控制台(System console)、计算机控制台(Computer console)、根控制台(Root console)、以及操作员控制台(Operator’s console)。事实上,早先的控制台是一种用来操作计算机的硬件,如图所示。52 https://en.wikipedia.org/wiki/System_console#/media/File:IBM_1620_Model_1.jpg从这幅图片中,我们可以看到 IBM 1620 计算机的控制台由左边的操作前面板和右边的打字机组成。通过控制台,操作员将文本数据或待执行的指令录入到计算机,并最终通过计算机读取或执行。

IBM 1620 的控制台

IBM 1620 的控制台

IBM 1620 控制台的操作前面板

IBM 1620 控制台的操作前面板

随着计算机的发展,控制台从硬件概念变成了一个软件概念。于是,控制台有了新的称呼:虚拟控制台。虚拟控制台正好与物理的控制台硬件相对。通过观察 Linux 系统的启动过程,我们不难发现:在经过计算机硬件自检之后,一旦由引导载入程序接管,不一会儿便会进入系统控制台。在这个过程中,通常会显示如图所示的 Linux 系统引导信息。53 https://en.wikipedia.org/wiki/Linux_console#/media/File:Knoppix-3.8-boot.png

Linux 系统虚拟控制台

Linux 系统虚拟控制台

终端

跟控制台一样,起初的终端(Terminal)也是一种计算机硬件设备。从外形上看,终端类似于我们今天所看到的显示器和键盘的结合体。通过终端,用户将指令和数据输入到计算机。同时,终端也将计算机执行的结果展示给用户。图中显示的是曾经广为流行的终端 DEC VT100。54 https://en.wikipedia.org/wiki/Computer_terminal#/media/File:DEC_VT100_terminal.jpg

DEC VT100 终端

DEC VT100 终端

或许你会产生疑问,为什么会出现终端这种硬件设备呢?以今天的眼光来看,显得似乎有些难以理解。诞生之初的计算机造价相当昂贵,可不像现在人人都能拥有一台那么简单。除了大型商业组织或大学研究机构,很难在别处看到计算机的身影。为了能够共享计算机资源,终端应运而生。然而,伴随着科技的进步,终端最终掉进了历史的黑洞。不过,它后来却以新的形式重生,这就是终端模拟器(Terminal emulator),或称之为虚拟终端。

终端模拟器

终端模拟器,即用来模拟终端硬件设备的应用程序。在物理终端中存在的某些显示体系结构,比如用来控制色彩的转义序列、光标位置等在终端模拟器中也得到了支持。下图显示 Linux 中流行的终端程序之一 XTerm。

XTerm 终端模拟器

XTerm 终端模拟器

不管是 Linux 操作系统,还是 macOS 操作系统,乃至 Windows 操作系统,今天都有许多终端模拟器可以选择。以下罗列的是这三个操作系统中比较流行的终端模拟器。

Linux

  • XTerm:XTerm 是 X 窗口环境的默认终端。它提供了与 DEC VT102 和 Tektronix 4014 终端兼容的特性。此外,它也支持 ISO/ANSI 彩色模式。
  • GNOME Terminal:GNOME Terminal 是 GNOME 桌面环境的默认终端。它提供了与 XTerm 相似的特性。除此之外,它也包括支持多配置、标签页、鼠标事件等其它功能。
  • Konsole:Konsole 是 KDE 桌面环境的默认终端。它包括标签页、多配置、书签支持、搜索等特性。
  • rxvt-unicode:rxvt-unicode 原本克隆自 rxvt,但加入了 unicode 支持,具有很强的定制特性。另外,rxvt-unicode 还包含 Daemon 模式、嵌入了 Perl 编程语言等功能。
  • Deepin Terminal:深度终端,包含 Quake 模式、标签页、窗口分割、远程管理等特色功能。

macOS

  • Terminal.app:Terminal.app 是 macOS 操作系统默认的终端。它的功能不多,除了提供设置 TERM 环境变量的选项外,还包括能够使用其搜索功能来查找 Man pages。
  • iTerm2:iTerm2 是 macOS 系统上针对默认终端的开源替代品。它非常流行,包含许多很棒的功能,比如窗口分割、自动补全、无鼠拷贝、粘贴历史等等。如果你在 macOS 上工作,那么不妨使用 iTerm2 这款终端模拟器,相信它所具有的功能一定不会让你失望。

Windows

  • Mintty:Mintty 是一个支持 Cygwin、MSYS、WSL 等多种环境的终端模拟器。它的功能与 XTerm 兼容,包括 256 色和真彩色、unicode、以及 Emoji 表情支持。
  • ConEmu:ConEmu 是 Windows 上一款相当流行的开源终端模拟器。它包含标签页、多种图形窗口模式、用户友好的文本块选择等功能。

Shell

Shell 是一种命令解释程序,它负责用户输入命令的读取、解析和执行。现代 Shell 除了具有与用户直接交互的特性之外,通常也包含编程功能,支持变量、数组、函数、循环、条件等编程基本要素。

Shell 之所以如此称呼,是由于它相对 Unix 及 Linux 的核心——内核(Kernel)而言,处于整个操作系统的最外层,就像乌龟的壳一样。也正因为如此,Shell 提供用来访问系统服务的用户界面,扮演着与内核交互的角色,如图所示。

Shell 与内核

Shell 与内核

在 Unix 及 Linux 的发展过程中,出现了许多种 Shell,其中比较知名的包括:sh、csh、ksh、bash、zsh 等等。

sh

sh,即 Bourne shell,它是 Unix 第 7 版的默认 Shell。Bourne shell 由贝尔实验室的 Stephen Bourne 开发,于 1979 年发布。随着《Unix 编程环境》(Brian Kernighan 与 Rob Pike 著)一书的出版,sh 变得大为流行。

Bourne shell 早已被后来的 Shell 所取代,现代 Linux 系统中的 sh 通常是符号链接的某个兼容 Shell。例如,所用的 Debian 里的 sh 为 dash。

root@toydroid:~# ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Jan 24  2017 /bin/sh -> dash

而在另一个系统 Arch Linux 上,sh 则为 bash。

root@codeland:~# ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb  7 15:15 /bin/sh -> bash

csh

csh 是 C shell 的简称,它由 Bill Joy 开发,通过 BSD 得到了广泛的分发。在风格上,开发者将 csh 设计得像 C 编程语言一样,因而由此得名。同时,csh 具有很不错的交互使用体验。后来被其它 Shell 所吸收的诸如历史、别名、目录栈、文件名补全、作业控制等特性均出自 csh。

csh 有一个改进版本叫 tcsh,目前是 FreeBSD 的默认 Shell。

ksh

ksh 指 Korn Shell,其开发者为 David Korn,在 1983 年公布于世。ksh 遵循 POSIX 标准,能够向下兼容 Bourne shell,整合了来自 C shell 的诸多特性。ksh 的一大亮点是引入了 vi 和 Emacs 风格的命令行编辑模式,使用户完全可以按照自己的按键习惯操作。此外,在 ksh 中还增加了关联数组的特性。

由于 ksh 最初以私有软件的形式进行分发,从而被限制了传播。代之以出现的替代品包括 pdksh(public domain ksh,公有域的 ksh)、mksh(后成为 Android 的默认 Shell)等。

bash

bash 作为理查德·斯托曼 GNU 工程的一部分出现,从它诞生之初就是为了用来取代 Bourne shell。Brian Fox 开发了最初的 bash,首个版本发布于 1989 年。如今,bash 已变得十分流行,它是大多数 Linux 发行版以及 macOS 的默认 Shell。此外,通过 WSL(Windows Subsystem for Linux),在 Windows 10 中也可以安装并使用 bash。

bash 的名称来自于 Bourne-again shell,它也遵循 POSIX 标准,其特性吸收自 sh、csh、ksh 等多种 Shell。

zsh

zsh 是 Z shell 的简称,最初的版本由 Paul Falstad 所开发,发布于 1990 年。zsh 极大的扩展了 Bourne shell 的功能,并包含来自 tcsh、ksh、bash 等 Shell 的特性。

在交互用户体验上,zsh 尤其出彩。比如,它支持对命令的选项进行补全、可以设置右提示符等,如图所示。

zsh 的右提示符

zsh 的右提示符

Linux 观测入门

观测策略

OODA 循环(OODA loop)是用于观测场景的一个策略。它提供一种结构化的方法来测试基于假设的观测数据,并据此采取行动。即,一种从信号获得可行动洞见的方法。

例如,应用程序运行缓慢。

  1. 假定有多种可能原因:没有足够的内存、CPU 执行周期太短、网络 I/O 不够等
  2. 测量每种资源的消耗
  3. 单独更改每种资源的分配,并测量输出
  4. 在提供更多内存后改进了应用程序的性能吗,若是,则找到了原因;若否,则继续对其它资源进行调整

概念

信号类型

日志(Logs)

每个系统的基本信号类型。

/var/log

/var/log

  1. apt 的日志
  2. 登录及验证处理日志
  3. 失败的登录日志
  4. 打印相关日志
  5. dpkg 的日志
  6. 设备驱动的日志
  7. 系统安装日志
  8. systemd 日志
  9. 内核日志
  10. 用户最后登录日志
  11. ntp 相关日志
  12. 系统日志

指标(Metrics)

以时间序列形式采样的数值。一般通过监视来捕捉系统和应用程序的指标。

显示基本的指标

  • uptime:系统运行好久、负载均值
  • free -h:内存占用
  • vmstat 1:内存状态
  • iostat -z --human:监视 I/O 设备
  • ss -atup:网络套接字统计
  • lsof -i TCP:1-1024:网络连接

集中的性能监视

  • top:CPU、内存、进程
  • htop:top 增强版,具有更好的用户界面
  • atop:除了 CPU、内存外,还包括 I/O、网络状态
  • glanceshttps://nicolargo.github.io/glances/

踪迹(Traces)

动态收集运行时信息。

跟踪来源

  • 内核:由内核中的函数或系统调用触发
  • 用户空间:应用程序的函数调用

使用场景

  • strace:调试程序
  • perf:性能分析
  • eBPF:将成为实现跟踪的默认标准

Linux 性能观测工具

Linux 性能观测工具

Linux 性能观测工具

(来源)

Nebula:可扩展的 overlay 网络

Overlay 网络

Overlay(覆盖)网络指在现有的物理网络之上创建的虚拟或逻辑网络。

Overlay 网络

Overlay 网络

例子:internet、SDN(software-defined networking)

Nebula 简介

Nebula 是专注于性能、简洁及安全的可扩展 overlay 网络工具。利用它,可以将世界各地的计算机无缝连接在一起。它支持的系统包括 Linux、FreeBSD、macOS、Windows、iOS 及 Android。Nebula 不仅能用于连接少量计算机,而且也能连接成千上万的计算机。

Nebula 特点

使用印象

参考

HTTP 的发展

HTTP(HyperText Transfer Protocol,超文本传输协议)是 WWW(万维网)的基础协议,最初由 Tim Berners-Lee 和他的团队在 1989-1991 年期间开发。HTTP 发生了太多的变化,在保持协议简单性的同时,不断扩展其灵活性。如今,HTTP 已经从一个只在实验室之间交换文件的早期协议进化到了现代复杂的互联网协议。

万维网的发明

1989 年,在 CERN 工作时,Tim Berners-Lee 编写了透过英特网构建超文本系统的提案。开始叫 Mesh,后来改为 World Wide Web。透过现有的 TCP 及 IP 协议构建,它由 4 个部分组成:

  1. 表示超文本文档的格式 HyperText Markup Language (HTML)
  2. 交换这些文档的协议 HyperText Transfer Protocol (HTTP)
  3. 呈现(及编辑)这些文档的客户端 WorldWideWeb(第一个网络浏览器)
  4. 给予访问文档的服务器 httpd

HTTP/0.9 - 单行协议

HTTP 的最初版本没有版本号,后来叫 0.9。HTTP/0.9 非常简单,请求只有一行:

GET /mypage.html

响应也很简单,只有文件本身:

<html>
  A very simple HTML page
</html>

HTTP/1.0 - 构建可扩展性

HTTP/0.9 很有限,但浏览器和服务器迅速使它功能更多:

此时,一个典型的请求和响应看起来像:

GET /mypage.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

200 OK
Date: Tue, 15 Nov 1994 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html
<HTML>
A page with an image
  <IMG SRC="/myimage.gif">
</HTML>

由服务器和浏览器添加的功能及解决的问题最后形成了 RFC 1945 文档,并定义为 HTTP/1.0。

HTTP/1.1 - 标准化协议

在实现 HTTP/1.0 的同时,也在并行推进协议的标准化。HTTP 的第一个标准化版本 HTTP/1.1 于 1997 年初发布。HTTP/1.1 引入了许多改进:

一个典型的请求流:

GET /en-US/docs/Glossary/Simple_header HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/en-US/docs/Glossary/Simple_header

200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Wed, 20 Jul 2016 10:55:30 GMT
Etag: "547fa7e369ef56031dd3bff2ace9fc0832eb251a"
Keep-Alive: timeout=5, max=1000
Last-Modified: Tue, 19 Jul 2016 00:59:33 GMT
Server: Apache
Transfer-Encoding: chunked
Vary: Cookie, Accept-Encoding

(content)

HTTP/1.1 作为 RFC 2068 发布。

HTTP/2 - 更好的性能

在 HTTP/2 发布之前,HTTP/1.1 稳定运行了超过 15 年,并在下列方面进行了扩展:

网页变得越来越复杂,更多的数据传输意味着更多的 HTTP 请求。2010 年初,Google 实现了一个试验协议 SPDY。SPDY 增加了响应性,并解决了重复数据的传输问题,成为 HTTP/2 的基础。

HTTP/2 与 HTTP/1.1 的差异:

HTTP/2 在 2015 年正式标准化。截止 2022-01,全球大约 46.9% 的网站使用。

HTTP/3 - 透过 QUIC 的 HTTP

HTTP/3 使用 QUIC 协议代替 TCP 协议。截止 2022-10,全球大约 26% 的网站使用。

HTTP/3 于 2022 年在 RFC 9114 中定义。

参考

ZFS:Zettabyte File System(泽字节文件系统)

简介

ZFS 是一个具有卷管理能力的文件系统。最初是 Sun Microsystems Solaris 操作系统的一部分,后来随开源的 OpenSolaris 发布。在 Oracle 收购 Sun Microsystems 后,将其闭源。2005 ~ 2010 年期间,ZFS 的开源版本被移植到 Linux、FreeBSD、Mac OS X。2013 年,OpenZFS 创建来用于协作开源 ZFS 的开发。

存储数据管理一般包括两个方面:

  1. 一个或多个块存储设备(如:硬盘、SD 卡)的物理卷管理
  2. 存储在逻辑块设备上的数据及文件管理

ZFS 与其它文件系统的不同之处在于,它统一了存储系统的这两种角色,既是卷管理器,也是文件系统。ZFS 被设计成确保存储在磁盘上的数据不会因硬件或操作系统的物理错误或错误处理而丢失。ZFS 也包含数据集和池级快照及复制机制。

ZFS 存储池

ZFS 存储池

特性

ZFS 特性非常丰富,以下是几个典型的代表:

许可

ZFS 许可协议为 CDDL,与 GPL 不兼容,故不能随 Linux 内核一起分发。

安装

apt update
apt install zfs-dkms zfsutils-linux

用法

创建存储池,raidz vdev:

# zpool create -f -m /mnt/data bigdata \
               raidz \
                  ata-ST3000DM001-9YN166_S1F0KDGY \
                  ata-ST3000DM001-9YN166_S1F0JKRR \
                  ata-ST3000DM001-9YN166_S1F0KBP8 \
                  ata-ST3000DM001-9YN166_S1F0JTM1

创建数据集:

# zfs create <nameofzpool>/<nameofdataset>

参考