Linux 操作系统必知必会

 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 岁)

上面这段话大致意思是:我写了一个加强版的操作系统实验,现在与大家分享,发布在 comp.os.minix,跑的都是 GNU 的程序:gcc, bash, ...,依赖 Minix 的工具链,从零开始做东西是不现实的。

Minix?

Linux 操作系统必知必会_第1张图片

Minix: 完全用于教学的真实操作系统 by Andrew S. Tanenbaum

年轻人的第一个 “全功能” 操作系统

Minix1 (1987): UNIXv7 兼容:Linus 实现 Linux 的起点

Minix2 (1997): POSIX 兼容:更加完备的系统,书后附全部内核代码

Linux 操作系统必知必会_第2张图片

Minix3 (2006): POSIX/NetBSD 兼容:一度是世界上应用最广的操作系统,Intel ME 人手一个

Linux 起飞

Linux 操作系统必知必会_第3张图片

  • Linux 2.0 引入多处理器 (Big Kernel Lock, 内核不能并行)
  • Linux 2.4 内核并行
  • 2002 年才引入 Read-Copy-Update (RCU) 无锁同步
  • 2003 年 Linux 2.6 发布,随云计算开始起飞

Linux 的 “两面”

专注的内核

  • 加载第一个进程
    • 相当于在操作系统中 “放置一个位于初始状态的状态机”
    • Single user model (高权限)
  • 包含一些进程可操纵的操作系统对象
  • 除此之外 “什么也没有”
    • Linux 变为一个中断 (系统调用) 处理程序

百家争鸣的生态

  • 系统工具 coreutils, binutils, systemd, ...
  • 桌面系统 Gnome, xfce, Android
  • 应用程序 file manager, vscode, ...

构建最小Linux

你完全可以构建一个 “只有一个文件” 的 Linux 系统——Linux 系统会首先加载一个 “init RAM Disk” 或 “init RAM FS”,在作系统最小初始化完成后,将控制权移交给 “第一个进程”。借助互联网或人工智能,你能够找到正确的文档,例如 The kernel’s command-line parameters 描述了所有能传递给 Linux Kernel 的命令行选项。

恰恰是 UNIX “干净” 的设计 (完成初始化后将控制权移交给第一个进程) 使得 Linus 可以在可控的工程代价下实现 (相当完善的) POSIX 兼容,从而掀起一场操作系统的革命。时至今日,实现接口级的兼容已经是一件极为困难的工程问题,典型的例子是微软的工程师最终抛弃了 API 行为兼容的 Windows Subsystem for Linux 1.0,进而转向了虚拟机上运行的 Linux 内核。

我们来看一个最小 Linux 的例子:用 QEMU 在给定的 Linux 内核完成初始化后,直接执行我自己编写的、静态链接的 init 二进制文件。

#!/bin/busybox sh

# initrd, only busybox and /init
BB=/bin/busybox

# (1) Print something and exit
$BB echo -e "\033[31mHello, OS World\033[0m"
$BB poweroff -f

# (2) Run a shell on the init console
$BB sh

# (3) Rock'n Roll!
for cmd in $($BB --list); do
  $BB ln -s $BB /bin/$cmd
done
mkdir -p /tmp
mkdir -p /proc && mount -t proc  none /proc
mkdir -p /sys  && mount -t sysfs none /sys
mknod /dev/tty c 4 1
setsid /bin/sh /dev/tty 2>&1
#include 

.globl _start
_start:
  movq $SYS_write, %rax   // write(
  movq $1,         %rdi   //   fd=1,
  movq $st,        %rsi   //   buf=st,
  movq $(ed - st), %rdx   //   count=ed-st
  syscall                 // );

  movq $SYS_exit,  %rax   // exit(
  movq $1,         %rdi   //   status=1
  syscall                 // );

st:
  .ascii "\033[01;31mHello, OS World\033[0m\n"
ed:
# Requires statically linked busybox

INIT := /init

initramfs:
# Copy kernel and busybox from the host system
	@mkdir -p build/initramfs/bin
	sudo bash -c "cp /boot/vmlinuz build/ && chmod 666 build/vmlinuz"
	cp init build/initramfs/
	cp $(shell which busybox) build/initramfs/bin/

# Pack build/initramfs as gzipped cpio archive
	cd build/initramfs && \
	  find . -print0 \
	  | cpio --null -ov --format=newc \
	  | gzip -9 > ../initramfs.cpio.gz

run:
# Run QEMU with the installed kernel and generated initramfs
	qemu-system-x86_64 \
	  -serial mon:stdio \
	  -kernel build/vmlinuz \
	  -initrd build/initramfs.cpio.gz \
	  -machine accel=kvm:tcg \
	  -append "console=ttyS0 quiet rdinit=$(INIT)"

clean:
	rm -rf build

.PHONY: initramfs run clean

 通过 initrd 执行我自己编写的、静态链接的 init 二进制文件。

initrd之后

initrd: 并不是我们实际看到的 Linux,只是一个内存里的小文件系统

  • 我们 “看到” 的都是被 init 创造出来的
    • 加载剩余必要的驱动程序,例如网卡
    • 根据 fstab 中的信息挂载文件系统,例如网络驱动器
    • 将根文件系统和控制权移交给另一个程序,例如 systemd

构建一个 “真正” 的应用世界

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.
  • 执行 /usr/sbin (Kernel 的 init 选项)
    • 看一看系统里的文件是什么吧
    • 计算机系统没有魔法 (一切都有合适的解释)

例子:NOILinux Lite

在 init 时多做一些事

export PATH=/bin
busybox mknod /dev/sda b 8 0
busybox mkdir -p /newroot
busybox mount -t ext2 /dev/sda /newroot
exec busybox switch_root /newroot/ /etc/init
  • pivot_root 之后才加载网卡驱动、配置 IP
    • 这些都是 systemd 的工作
    • (你会留意到 tty 字体变了)
  • 之后 initramfs 就功成身退,资源释放

你可能感兴趣的:(linux,运维,服务器)