本文将记录《how linux works》一书中的知识。

第一章 概述

Linux层次

Linux分为用户进程,Linux内核,硬件。
Linux分层
内核在硬件之上管理硬件系统,是硬件系统和应用程序之间进行通信的接口

进程指计算机中运行的所有程序,组成了最顶层,称作用户空间或用户进程

用户进程与内核之间最主要的区别是内核在内核模式 kernel mode中运行,用户进程在用户模式运行。内核模式中运行不受任何限制访问处理器与内存。那些只有内核可以访问的空间叫做内存空间 kernel space,反之用户进程可以访问的为用户空间 user space
一般来说用户进程的影响范围被限制在用户空间内。

主内存

与CPU频繁产生读取行为的内存。数据以特定排列的0与1 bit存储,这被称为状态 state。我们可以用状态变化阶段来描述进程的执行过程(eg. 进程的执行阶段 ,进程正在执行启动任务阶段)。
镜像 image 通常表示比特值在内存中的特定物理排列

内核

内存负责管理以下四个方面:

  • 进程:决定哪个进程可以使用CPU
  • 内存:内存分配,管理进程间的共享内存与空闲内存
  • 设备驱动程序:作为硬件系统和进程之间的接口
  • 系统调用和支持: 进程使用系统调用和进程通信

进程管理

进程轮流使用CPU实现同时运行多个进程,被称作多任务执行。CPU从执行一个进程切换到执行另一个进程就叫做上下文切换 context swich

  1. CPU停止A进程,由内核接管CPU控制权
  2. 内核记录下但前CPU和内存的状态信息,在恢复进程时使用
  3. 内核执行上个时间段内被悬置的任务(输入输出,磁盘读写)
  4. 内核准备执行下一个进程,从准备就绪的进程中选择一个执行
  5. 内核为B进程准备CPU与内存
  6. 内核将新进程执行时间段通知CPU
  7. 内核将CPU切换至用户模式,将CPU控制权移交给新进程

内核在什么时候运行的?
在上下文切换时的时间段间隙中运行的

内存管理

内核在上下文切换过程中管理内存,内核要保证以下条件

  • 内核自己的专有内存空间
  • 每个用户进程的专有空间
  • 用户进程之间的共享空间
  • 用户进程的某些内存空间可以是只读
  • 交换空间 swap space 扩展出比实际内存容量更大的内存空间

MMU 内存管理单元 Memory Management Unit
让进程不是直接访问内存的实际物理地质,而是通过MMU截获进程的访问请求通过内存映射表将虚拟地址转换为世纪物理地址。内核将会维护这张表

内存映射地址使用页表 page table 实现

驱动程序

设备驱动程序在传统意义上来说也是内核的一部分,作用都是为用户进程提供统一的结构,使用硬件设备。

系统调用和系统支持

系统调用 system call
有时候用户进程需要执行一些不方便或是无法完成的工作。 打开,读取,写文件这些操作都涉及系统调用。
fork(): 当进程调用fork时,内核创建一个和该进程几乎一样的副本
exec(): 当进程调用exec(program) 内核启动program来替换当前进程
除了init外,Linux中所有的用户进程都是通过fork()来启动的。除了创建现有进程的副本外,多数情况下你还可以使用exec() 来启动新的进程。
当你在terminal中输入ls时会发生什么?
终端窗口中的shell调用fork()创建一个shell副本,这时候有了两个一样的shell进程,然后该副本调用exec(ls) 来运行ls。

内核还为用户进程提供了许多功能,比如虚拟设备。虚拟设备是用软件模式出的硬件设备,技术上来说这并不需要存在与内核中,但是就实现难度来说,放在内核中要小的多,比如岁技术生成器 (/dev/random)

用户空间

不同的用户进程被分配了独立的用户空间执行了不同的任务。

用户

Linux内核继承了UNIX的用户概念。早期还为产生PC这一概念时,多终端使用统一台设备,会有多个用户。
内核通过用户ID管理用户。每一个用户进程都有一个用户所有者。管理员用户即root拥有超级权限。

虽然root用户权限很高但是还是在用户模式而非内核模式

第二章 基础命令

Linux 默认 Shell是最初的Bourne Shell的增强版,称之为bash Bourne-again shell

标准输入输出

进程向输入流中读取数据向输出流中写出数据。
在终端中输入

1
cat

当只输入cat时就从Linux内核提供的默认标准输入流中获得输入数据,这是运行cat命令的终端就成了标准输入。这时候你输入任意字符就会在回显出来。
CRTL+D 终止当前终端的标准输入并种植命令
CRTL+C 种植当前进程的运行,无论是否有输入输出

标准输出也与之类似。在cat运行时标准输出就和该终端建立了连接,所以看到了回显

标准输入和标准输出简写为stdin 和 stdout。 很多命令和cat一样如果不指定输入文件就从标准输入获得输入。 而输出有点不同,有部分命令会将数据直接输出到文件。
Linux 中 . 代表当前目录 eg. ./mydir/ ..代表上级目录eg. cd ../../usr

通配符

shell中 * 代表仍以字符和数字
Shell 根据通配符匹配文件, Shell 将命令中的参数替换为实际的文件名,这个过程叫做展开

  • at* 展开为所有以at结尾文件名;
  • *at 展开为所有以at开头文件名;
  • at 展开为所有包含at文件名;

使用? 匹配任意一个字符 eg. b?at 匹配 boatbrat

如果通配符没有匹配的文件名shell就不会进行展开

如果不想要展开可以使用 '*' 转义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//打印
echo Hello there
//查看文件内容
cat /etc/passwd
//查看多个文件
cat file1 file2
//查看文件列表信息
ls -l
//隐藏文件
ls -a
// 复制文件
cp file file1
// 多个文件复制到dir
cp file1 .... fileN dir
// 重命名
mv file file1
// 移动多个文件
mv file1 .... fileN dir
//创建文件
touch file
//删除文件
rm file
//移动当前目录
cd dir
//创建文件夹
mkdir dir
//产出文件夹,前提空文件夹
rmdir dir
// grep -i 不区分大小写 -v 反转匹配,所有不匹配的 egrep 等同于 grep -E 启用正则表达式
// .* 匹配任意多个字符
// . 匹配任意一个字符
在passwd文件中查找root
grep root /etc/passwd
//more命令的增强版 空格查看下一屏 B查看上一屏 Q 退出 /word 向下匹配word ?word向上匹配
less file
//显示当前目录
pwd
//比较文件
diff file1 file2
//文件详细信息
file file
//在 dir目录下查找file文件
find dir -name file -print
//在索引中查找,Linux内核维护着文件索引,定期更新,如果你创建了一个新的文件,它可能不在索引里
locate dir -name file -print
//查看文件头部
head
//查看文件尾部
tail
//按照字母数字顺序排序 -r 反向排序
sort
//重定向符将输出重定向到文件eg. cat README.md > readme.out
command > file
//输出不覆盖加入到文件末尾
command >> file

环境变量和Shell变量

通过$ 使用声明过的Shell变量
环境变量和Shell变量最大的区别是Shell变量只能被当前Shell所使用

1
2
3
4
5
//shell 变量
STUFF=blah
echo $STUFF
//环境变量
export STUFF

命令路径

与环境变量相似,在路径被加入命令路径下之后,其下的文件执行可以在任意路径中使用命令执行而不需要指定路径。

1
2
3
4
echo $PATH
/home/kurami/.nvm/versions/node/v16.20.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/kurami/.local/share/JetBrains/Toolbox/scripts
//添加命令路径
PATH=$PATH:dir

命令行编辑

一些快捷方式帮助你比箭头更方便的编辑

1
2
3
4
5
6
7
8
9
10
CTRL+B 左移
CTRL+F 右移
CTRL+P 查看上一条命令
CTRL+N 查看下一条命令
CTRL+A 移动光标到行首 home
CTRL+E 移动光标到行尾 end
CTRL+W 删除前一个词
CTRL+U 删除从光标至行首内容
CTRL+K 删除从光标至行尾内容
CTRL+Y 粘贴已删除文本

目录结构

Linux目录结构

  • /bin 存放可执行文件,包括大部分基础的Unix命令大部分是由C编译器创建的二进制文件
  • /dev 设备文件
  • /etc 系统配置文件
  • /home 个人目录
  • /lib 共可执行文件使用的代码库
  • /proc 存放系统相关信息如当前运行的进程和内核信息
  • /sys 类似/proc
  • /sbin 可执行的系统文件,用来管理系统许多命令使用由root用户银杏
  • /tmp 临时文件 很多系统会在启动时清空该文件夹
  • /usr 存放许多Linux 系统文件
  • /var 存放运行时信息的地方 如系统直至,用户信息,缓存和其他信息