12 - Building the application ecosystem

12 - 构建应用生态

我们已经了解了一个典型的操作系统给应用程序提供的 “一切”:从操作系统为应用程序提供的对象和 API 到可执行文件的链接和加载,操作系统实现了管理硬件资源的底层机制。这是狭义 “操作系统” 负责的功能。

本讲内容:一个真实的 “操作系统”,如何使用操作系统的对象和 API,构建丰富的应用生态?其中又有怎样的实用工具起到了决定性的作用?

1. 从 UNIX 到 Linux

1.1. Evolution of the UNIX Time Sharing System

最早的版本甚至没有 fork

  1. Shell 关闭所有打开的文件,然后为 0, 1 fd 打开终端文件

    1. 单进程的 不支持多进程的

  2. 从终端读取命令行

  3. 打开文件,把加载器代码复制到内存并执行 (相当于 exec)

    1. 当时还没有 fork()

  4. exit 会重新加载 shell

    • Takeaway message: 不要害怕 “不好”,大胆去做,并且持续改进

      • 先做一堆垃圾出来

      • 见过的所有大系统,一开始都是几个大学生组队开发的...几个好朋友...

      • 最后就成功了

所以,从零开始做很重要

早期版本的操作系统其实和我们的 MiniLab 很像...

1.2. Minix

Minix1 (1987)

  • UNIXv7 兼容

  • Linus 实现 Linux 的起点

  • 同时兼容 16-bit 和 32-bit

    • 真实展示 16-bit 编程

Minix2 (1997)

  • POSIX 兼容

  • 随书附有代码

微内核的处理器,源代码很简单...甚至可以随书附赠...

这时候已经能实现现代 OS 的一些常用功能了...

Tips:Minix 是32位的,意味着 sizeof(int) == 2

1.3. 年轻人的第一个操作系统

Minix3 (2006): POSIX/NetBSD 兼容

  • 一度是世界上应用最广的操作系统 (Intel ME)

1.4. August, 1991, The Birthday of Linux

Hello, everybody out there using minix – I’m doing a (free) operating system (just a hobby, won’t be big and professional like gnu) for 386(486) AT clones. This has been brewing since April, and is starting to get ready.

—— Linus Torvalds (时年 21 岁)

类似于 “我写了个加强版的 OSLab,现在与大家分享”

  • 发布在 comp.os.minix

    • (“百度贴吧”)

    • 因为还依赖 Minix 的工具链 (从零开始做东西是不现实的)

    • 跑的都是 GNU 的程序:gcc, bash, ...

  • 合适的人、合适的时间

    • 386(486) 的时间点

    • 计算机硬件刚好起飞

1.5. "Just for fun"

The story of an accidental revolutionary

Revolutionaries aren’t born. Revolutions can’t be planned. Revolutions can’t be managed. Revolutions happen....

—— David Diamond (本书作者)

教育部印发《关于加强高校有组织科研 推动高水平自立自强的若干意见》

  • 就推动高校充分发挥新型举国体制优势,加强有组织科研,全面加强创新体系建设,着力提升自主创新能力,更高质量、更大贡献服务国家战略需求作出部署。

  • “在人-机-物融合时代实现操作系统的弯道 (换道) 超车”

在学校里总是被一些莫名其妙的事情拖住...因为我们的国家要生存...所以我们只能在夹缝中生存

1.6. "Linux is Obsolete" Debate

在 comp.os.minix 上关于 Linux 的讨论越来越多了

  • Andrew Tanenbaum 做出了 “官方回应”

    • 觉得 “太落后”

  • Linus 完全不服气

  • Ken Thompson 也参与了讨论

    • 他已经在 ~10 年前获得了图灵奖……

1.7. 后来的事

linux 代码指数增长???

  • Linux 2.0 引入多处理器 (Big Kernel Lock, 内核不能并行)

  • Linux 2.4 内核并行

  • 2002 年才引入 Read-Copy-Update (RCU) 无锁同步

  • 2003 年 Linux 2.6 发布,随云计算开始起飞

1.8. Linux 的“两面”

Kernel

  • 加载第一个进程

    • 相当于在操作系统中 “放置一个位于初始状态的状态机”

    • “Initramfs” 模式

  • 包含一些进程可操纵的操作系统对象

  • 除此之外 “什么也没有” (Kernel 就是一个 trap handler)

Linux Kernel 系统调用上的发行版和应用生态

2. Linux 和应用程序的接口 🌶️

2.1. 除了对象和系统调用 API

The last piece: “初始状态”

  • Everything is a state machine

    • “操作系统中的对象” 应该也有一个初始状态

它是什么呢?

  • 观察到 Linux 的系统更新

    • “update-initramfs... (漫长的等待)”

    • 这就是 Linux Kernel 启动后的 “初始状态”

2.2. initramfs

我们的 initramfs

  • 可以只有一个 init 文件

最小的 Linux...

    • 可以是任意的 binary,包括我们自己实现的

  • (系统启动后,Linux 还会增加 /dev 和 /dev/console)

    • 需要给 stdin/stdout/stderr 一个 “地方”

实际的 initramfs (我们可以解开来看一看)

  • 基本的命令行工具

  • 基础设备驱动程序 (可能从磁盘/网络挂载文件系统)

  • 文件系统工具 (万一磁盘损坏了,还能抢救一下)

2.3. 点亮 Linux 世界

Busybox utilities

[ [[ acpid adjtimex ar arch arp arping ash awk basename bc blkdiscard blockdev
brctl bunzip2 busybox bzcat bzip2 cal cat chgrp chmod chown chpasswd chroot
chvt clear cmp cp cpio crond crontab cttyhack cut date dc dd deallocvt depmod
devmem df diff dirname dmesg dnsdomainname dos2unix dpkg dpkg-deb du dumpkmap
dumpleases echo ed egrep env expand expr factor fallocate false fatattr fdisk
fgrep find fold free freeramdisk fsfreeze fstrim ftpget ftpput getopt getty
grep groups gunzip gzip halt head hexdump hostid hostname httpd hwclock
i2cdetect i2cdump i2cget i2cset id ifconfig ifdown ifup init insmod ionice ip
ipcalc ipneigh kill killall klogd last less link linux32 linux64 linuxrc ln
loadfont loadkmap logger login logname logread losetup ls lsmod lsscsi lzcat
lzma lzop md5sum mdev microcom mkdir mkdosfs mke2fs mkfifo mknod mkpasswd
mkswap mktemp modinfo modprobe more mount mt mv nameif nc netstat nl nologin
nproc nsenter nslookup nuke od openvt partprobe passwd paste patch pidof ping
ping6 pivot_root poweroff printf ps pwd rdate readlink realpath reboot renice
reset resume rev rm rmdir rmmod route rpm rpm2cpio run-init run-parts sed seq
setkeycodes setpriv setsid sh sha1sum sha256sum sha512sum shred shuf sleep sort
ssl_client start-stop-daemon stat static-sh strings stty su sulogin svc svok
swapoff swapon switch_root sync sysctl syslogd tac tail tar taskset tc tee
telnet telnetd test tftp time timeout top touch tr traceroute traceroute6 true
truncate tty tunctl ubirename udhcpc udhcpd uevent umount uname uncompress
unexpand uniq unix2dos unlink unlzma unshare unxz unzip uptime usleep uudecode
uuencode vconfig vi w watch watchdog wc wget which who whoami xargs xxd xz
xzcat yes zcat

2.4. 并不是我们平时“看到”的“Linux”世界

启动的初级阶段

  • 加载剩余必要的驱动程序,例如磁盘/网卡

  • 挂载必要的文件系统

    • Linux 内核有启动选项 (类似环境变量)

      • /proc/cmdline (man 7 bootparam)

    • 读取 root filesystem 的 /etc/fstab

  • 将根文件系统和控制权移交给另一个程序,例如 systemd

启动的第二级阶段

  • 看一看系统里的 /sbin/init 是什么?

  • 计算机系统没有魔法 (一切都有合适的解释)

2.5. 构建真正应用世界的系统调用

switch_root 命令背后的系统调用

int pivot_root(const char *new_root, const char *put_old);
  • pivot_root() changes the root mount in the mount namespace of the calling process. More precisely, it moves the root mount to the directory put_old and makes new_root the new root mount. The calling process must have the CAP_SYS_ADMIN capability in the user namespace that owns the caller's mount namespace.

  • syscalls(2)

2.6. 自己接管一切

创建一个磁盘镜像

  • /sbin/init 指向任何一个程序

    • 同样需要加载必要的驱动

    • 例子:pivot_root 之后才加载网卡驱动、配置 IP

    • 例子:tty 字体变化

      • 这些都是 systemd 的工作

  • 例子:NOILinux Lite

Initramfs 会被释放

  • 功成身退

2.7. That's All: 操作系统 = 对象的集合

初始状态

  • initramfs 中的对象 + /dev/console + 加载的 init

状态迁移

  • 选择一个进程 (对象) 执行一条指令

  • 系统调用指令

    • 进程管理: fork, execve, exit, waitpid, getpid, ...

    • 操作系统对象和访问: open, close, read, write, pipe, mount, mkfifo, mknod, stat, socket, ...

    • 地址空间管理: mmap, sbrk (mmap 的前身)

    • 以及一些其他的机制: pivot_root, chmod, chown, ...

3. 构建应用程序的世界

3.1. 操作系统是幕后的 MVP

仅有的机制

  • 初始状态 + 系统调用

操作系统完全 “感知不到” 应用程序

  • Shell: 系统管理的接口

  • 系统工具: grep, cat, gcc, ...

  • 应用程序: vscode, ...

  • 后台服务: sshd, httpd, ...

    • 嘿!AI 时代,操作系统也许可以 “感知” 应用了:为每一个 system call (甚至是 function call) 提供 “traceability”

3.2. 我们还是需要应用程序

前互联网时代

  • 软盘发行 (DOS) v.s. 光盘发行 (Windows 3.X/95)

    • 双击安装程序,输入 CD-Key (“破解” 简直太容易了)

  • 光驱:光盘驱动器...

今天呢?

  • 装应用哪那么麻烦;登录账号,自动管理,自动更新、……

3.3. 应用生态

应用商店模式

开源模式

  • 开发者维护代码

  • 和发行版团队共同维护应用仓库

3.4. Debian

Our Mission: Creating a Free Operating System

The Debian Project is an association of individuals, sharing a common goal: We want to create a free operating system, freely available for everyone. Now, when we use the word "free", we're not talking about money, instead, we are referring to software freedom.

  • CS 和其他任何学科都不同:开源开放

  • apt-get install firefox (1998)

    • 跨时代的 “Advanced Packaging Tool”

Debian 的包管理:“软件供应链”

3.5. Debian 软件包 deb

一个压缩包 (例子)

  • control.tar.xz

    • “control” 文件: Package, Source, Version, Architecture, Maintainer, Depends, Suggests, Section, Priority, Description, ...

  • data.tar.xz

    • 实际的文件 (绝对路径)

  • dpkg 可以安装 deb 包

    • 它也是操作系统上的一个普通应用程序 (使用系统调用完成 “安装” 功能)

3.6. 生态

为什么建设我们的生态那么艰难?

  • 生态的关键是开发者

  • 但 qualify 的开发者太少了

    • 大学四年都在写高血压代码?

    • 错误的设计 = 无法维护的泥潭

      • 课程的使命是让大家 “见识” 各种设计

      • 蒋门万岁!!!

AI 时代

  • “软件生态” 会消失吗?

    • 只需要一个 “最小” 的执行环境

    • AI 随时随地按需生成代码

4. 总结

正式结束了 Virtualization 部分的课程...虚拟化...

Take-away Messages: 至此,我们终于完全展示了逐层抽象的计算机系统世界:

  • 硬件向上提供了指令集体系结构

  • 基于指令集,实现了操作系统 (对象、系统调用 API 和 initramfs 定义的初始状态)

  • 操作系统上面支撑了系统工具 (coreutils, shell, apt, gcc, ...)

  • 系统工具上面才是各式各样的应用程序

实际上,我们看到的计算机系统中的一切都是由应用程序 “完成” 的,操作系统只是提供系统调用这个非常原始的服务接口。正是系统调用 (包括操作系统中的对象) 这个稳定的、向后兼容的接口随着历史演化和积累,形成了难以逾越的技术屏障,在颠覆性的技术革新到来之前,另起炉灶都是非常困难的。

Last updated