原理介绍
1. Linux
简介
1.1. Linux
系统结构
参考博客:
Linux
系结结构:
- 用户空间(User Space) :用户空间又包括用户的应用程序
(User Applications)
、C 库(C Library)
- 内核空间(Kernel Space) :内核空间又包括系统调用接口
(System Call Interface)
、内核(Kernel)
、平台架构相关的代码(Architecture-Dependent Kernel Code)
。
原因:
- 现代
CPU
实现了不同的工作模式,不同模式下CPU
可以执行的指令和访问的寄存器不同。 Linux
从CPU
的角度出发,为了保护内核的安全,把系统分成了两部分,防止用户程序不稳定把系统给搞崩溃。
1. 进程、内存:
- 内存分配:根据结构上的区分,内存被分为了两大块,两个空间有着各自的内存区域。
- 内核态: 当进程/线程运行在「内核空间」时就处于「内核态」。
CPU
可以执行任何指令- 代码不受任何的限制,可以自由地访问任何有效地址
- 代码也可以直接进行端口的访问
- 用户态: 当进程/线程运行在「用户空间」时则处于「用户态」。
- 代码执行要受到
CPU
的很多检查 - 访问内存地址受限制,比如:进程只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址。
- 代码执行要受到
- 所有系统资源的管理都是在「内核态」执行。
2. 用户态切换到内核态
原因:
所有系统资源的管理通过内核态完成,那我们应用程序需要访问磁盘,读取网卡的数据,新建一个线程都需要从「用户态」切换到「内存态」。
方式:
- 系统调用: 通过对系统提供的
API
接口函数进行调用,完成从「用户态」切换到「内存态」。 - 中断: 利用软中断
init 6
,用户可以进行系统重启。- 硬中断: 外部硬件状态发生改变所引起的中断;例如,插入一个u盘,网卡收到数据包的时候
- 软中断: 由当前进程所触发的中断;例如,
init 6
类型 | 触发 | CPU | 时间 | 案例 |
---|---|---|---|---|
硬中断 | 硬件触发 | 马上中断处理 | 较短时间内完成 | 插入一个u盘 |
软中断 | 进程触发 | 不一定马上运行 | 处理时间相对较长 | init 6 重启系统 |
[!tip|style:flat] 扩展:根据
CPU
运行情况,可以把「中断」分为「外中断」与「内中断」,执行逻辑顺序一样。
- 中断(外中断):「外中断」就是通常所述的「中断」,由
CPU
外部事件所触发的。- 异常(内中断):
CPU
内部程序运行,指令执行出错,把程序玩崩溃了。参考博客:中断与异常的区别
1.2. 内核
[!note|style:flat] 作用:Linux系统的核心是内核(
kernel space
,这里的「内核」是指的是「内核空间」里面的东西)。内核控制着计算机系统上的所有硬件和软件,在必要时分配硬件,并根据需要执行软件。
- 系统内存管理``
- 应用程序管理
- 硬件设备管理
- 文件系统管理
1.3. 内存管理
1. MMU 内存管理单元
介绍: 一个硬件芯片,用来将virtual memory
映射到真正的物理设备地址上。也就是说CPU
是通过MMU
来找到真正的内存条,硬盘,显卡等硬件的位置。
2. virtual memory
对32
位的CPU
而言,就会构造一个地址范围为0x00000000 ~ 0xFFFFFFFF
的「虚拟内存」,然后通过Memory Management
将物理内存Memory
(内存条)和Swap Space
(硬盘上的模拟内存)映射到虚拟内存上,同样还有其他硬件的可操作内存都映射到这上面(例如显存)。这样做的好处就是:将零碎的可访问地址统一集中起来,CPU
中的指令就只需要根据地址编号0x00000000 ~ 0xFFFFFFFF
读写对应的内存就行了,具体的找地址工作就交给「内存管理单元MMU
」完成。
[!tip]
- 我们编写的程序都是以
virtual memory
进行内存寻址的,运行时,也可以看成是在「虚拟地址空间」中运行的。真实的物理寻址则靠MMU
完成。- 每个进程都有自己独立的虚拟地址空间,运行时,就将虚拟地址空间里的代码数据映射到内存中,从而被CPU执行与处理。
上图的内存映射是乱画的,真实情况不知道(懒得查了)
虚拟内存的全局图:
下面进行程序测试,同样的程序同时运行,其内存地址是一样。通过MMU
单元翻译过后的物理地址也应该是一样的。「这就产生问题了,同时运行的程序,其所在的内存地址应该要不一样才行阿。」
在CPU
中执行的代码只是完整程序的一部分,对于上面所遇到的两进程同时运行造成的问题,只要系统将进程运行时间错开,再运行就行了,表面上的同时运行,其实对于CPU
而言是错开了的。
进程1:
进程2:
3. swap space
swap space
:就是一块磁盘空间(硬盘空间)。虚拟内存与物理内存映射的时候,当物理内存不够用时,会将代码放到「交换区」中,以后在CPU
想要执行相关的指令或者数据时,如果内存中没有,先去交换区将需要的指令与数据搬到物理内存,然后CPU
再执行。
在CPU
中执行的代码只是完整程序的一部分,CPU
是会以时间片的形式轮换执行多个程序;在这里swap space
就充当了一个「休息室」,当「物理内存」中客流量大时(内存被占用的太厉害),就将「物理内存」中还有一段时间才能切换到的空闲程序给撤下来,放到「交换区」里等着,别占用「物理内存」,等到要运行的时候,又将程序与数据加载回「物理内存」。通过swap space
这就能实现多个需要大内存运行的程序,能在储存量小的物理内存上同时运。
4. cache/buffer
- cache:缓存,用来加速「读」操作;先把从磁盘读取的数据保存到内存中,然后
CPU
使用时,直接从内存中读取,效率更块。 - buffer:缓冲区,用来加速「写」操作;先把要写出的数据保存到内存中,达到一定数量后,然后
CPU
集中将数据写入磁盘。
1.4. 应用程序管理
Linux
操作系统将运行中的程序称为「进程」。每个进程分配一个「virtual memory」,真正在物理内存上运行的就只是其中一小部分。 进程可以在前台运行,将输出显示在屏幕上,也可以在后台运行,隐藏到幕后。内核控制着Linux
系统如何管理运行在系统上的所有进程。
1. init
进程
linux
系统启动后,第一个被创建的「用户态」进程就是init
进程。
- 执行系统初始化脚本,创建一系列的进程(它们都是
init
进程的子孙); - 在一个死循环中等待其子进程的退出事件,并调用
waitid
用来完成「收尸」工作; init
进程不会被暂停PID
永远为1
2. 7大运行级别
[!tip]
0
:系统停机1
:单用户工作状态,root权限,用于系统维护,禁止远程登陆2
:多用户状态(没有NFS
,网络文件系统)3
:完全的多用户状态(有NFS
,网络文件系统),登陆后进入控制台命令行模式4
:系统未使用,保留5
:X11控制台,桌面模式6
:系统正常关闭并重启
1.5. 硬件设备管理
任何Linux
系统需要与之通信的设备,都需要在内核代码中加入对应的「驱动程序代码」。驱动程序代码相当于应用程序和硬件设备的中间人,允许内核与设备之间交换数据。
在Linux
内核中有两种方法用于插入设备驱动代码:
- 编译进内核的设备驱动代码:加入代码,重新编译内核
- 可插入内核的设备驱动模块:允许将驱动代码插入到运行中的内核而无需重新编译内核。当设备不再使用时也可将内核模块从内核中移走。
1.6. 文件系统管理
- 内核必须在编译时就加入对所有可能用到的文件系统的支持
Linux
内核采用虚拟文件系统(Virtual File System,VFS)
作为和每个文件系统交互的接口
ext | Linux扩展文件系统,最早的Linux文件系统
ext2 | 第二扩展文件系统,在ext的基础上提供了更多的功能
ext3 | 第三扩展文件系统,支持日志功能
ext4 | 第四扩展文件系统,支持高级日志功能
hpfs | OS/2高性能文件系统
jfs | IBM日志文件系统
iso9660 | ISO 9660文件系统(CD-ROM)
minix | MINIX文件系统
msdos | 微软的FAT16
ncp | Netware文件系统
nfs | 网络文件系统
ntfs | 支持Microsoft NT文件系统
proc | 访问系统信息
ReiserFS | 高级Linux文件系统,能提供更好的性能和硬盘恢复功能
smb | 支持网络访问的Samba SMB文件系统
sysv | 较早期的Unix文件系统
ufs | BSD文件系统
umsdos | 建立在msdos上的类Unix文件系统
vfat | Windows 95文件系统(FAT32)
XFS | 高性能64位日志文件系统
2. linux
的启动过程
- 主机加电自检,加载
BIOS
硬件信息。 - 读取
MBR
的引导文件(GRUB、LILO)。 - 引导
Linux
内核。 - 运行第一个进程
init
(进程号永远为 1 )。 - 进入相应的「运行级别」。
- 运行终端,输入用户名和密码。
3. 文件
参考博客:
3.1. 概念
[!warning|style:flat] 在
Linux
系统中,一切皆是文件。
3.2. 文件属性
3.3. 七种文件类型
- 普通文件类型:
-
Linux
中最多的一种文件类型, 包括 纯文本文件(ASCII)
;二进制文件(binary)
;数据格式的文件(data)
;各种压缩文件
- 目录文件:
d
- 就是文件夹
- 块设备文件:
b
- 就是存储数据以供系统存取的接口设备,简单而言就是「硬盘」。例如一号硬盘的代码是
/dev/hda1
等文件。
- 就是存储数据以供系统存取的接口设备,简单而言就是「硬盘」。例如一号硬盘的代码是
- 字符设备:
c
- 串行端口的接口设备,例如键盘、鼠标等等。
- 套接字文件:
s
- 这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。最常在
/var/run
目录中看到这种文件类型
- 这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。最常在
- 管道文件:
p
FIFO
也是一种特殊的文件类型,它主要的目的是进程间通讯。
- 链接文件:
l
- 类似
Windows
下面的快捷方式。
- 类似
3.4. 文件权限
- 文件的访问对象分为: u用户,g组,o其他 ;
- 文件的访问权限分为: r,w,x 对应二进制 111
3.5. 文件时间戳
[!note]
- 访问时间
(acces)
(-atime
天,-amin
分钟):文件被查看的时间,用户最近一次访问时间。- 修改时间
(modify)
(-mtime
天,-mmin
分钟):「内容数据」被修改的最后一次修改时间。- 变化时间
(change)
(-ctime
天,-cmin
分钟):状态时间,当文件的状态即文件的属性被改变是就会更改这个时间,例如文件系统中的links
(链接数),size
(文件的大小)、文件的权限、blocks
(文件的block
数);
3.6. 目录的结构
硬盘内存的划分:
- 导引块: 加载硬盘数据用的程序
- 专用块: 磁盘相关信息,例如,磁盘大小。
i
节点表块: 存储所有的i
节点- 数据存储块: 文件数据
目录
- 目录: 包含「一组目录项」的「文件」
- 目录项: 由「文件名」与「i节点索引」
- i节点: 指向该文件在硬盘上的「数据存储块」,还包含了很多信息,文件的创建者、文件的创建日期、文件的大小等等,唯独不记录文件名。
- 文件:每一个文件都对应着一个「i节点」
[!note|style:flat] 对于
linux
而言默认的一个block
为4096
个字节,对应硬盘8
个扇区。由于「文件夹」其实就是「目录」,即也是存储在硬盘上的一个「文件」,默认分配大小就是一个block
,所以一个「文件夹」会显示大小为4096
链接
[!tip]
- 硬链接: 多个「目录项」绑定到了同一片「数据储存块」(也就是同一文件);「硬链接」会使得「链接计数器」增加,计数器表示了当前文件被多少个文件绑定,当计数器为
0
时,该文件才能真正被删除。
- 只有超级用户才可以为目录创建硬链接
- 不可以在不同文件系统的文件间建立链接
- 符号链接: 是一个包含「i结点」路径的一个索引。
- 软链接克服了硬链接的不足
- 当原始文件位置变动或者被删除,软连接失效。
4. 文件描述符与进程
4.1. 进程
1. task_struct
对于操作系统,进程就是一个数据结构:
struct task_struct {
// 进程状态
long state;
// 虚拟内存结构体
struct mm_struct *mm;
// 进程号
pid_t pid;
// 指向父进程的指针
struct task_struct __rcu *parent;
// 子进程列表
struct list_head children;
// 存放文件系统信息的指针
struct fs_struct *fs;
// 一个数组,包含该进程打开的文件指针
struct files_struct *files;
};
- mm
: 指向的是进程的虚拟内存,也就是载入资源和可执行文件的地方
- files
:这个数组里装着所有该进程打开的文件的指针
2. 进程与线程
[!note|style:flat] 对于
linux
但无论线程还是进程,都是用task_struct
结构表示的,唯一的区别就是共享的数据区域不同。
4.2. 文件描述符
定义:每个进程被创建时,files 的前三位被填入默认值,分别指向「标准输入流」、「标准输出流」、「标准错误流」。我们常说的「文件描述符」就是指这个文件指针数组的索引。
[!tip]
0
: 就是stdin
1
: 就是stdout
2
: 就是stderr
由于在linux
中,定义一切内容皆是文件,那么要操作什么外部内容就可以往这个files
结构体中插入「文件」进行操作。
4.3. 重定向
1. 输入重定向
原理:就是把files[0]
修改掉。
2. 输出重定向
原理:就是把files[1]
修改掉。
4.4. 他位置的文件描述符
[!tip]
A >& B
:
A,B
:files[]
的索引数字&
:将B
与A
绑定> <
:是输入替换,还是输出替换。
5. 环境变量
参考博客:
5.1. 定义
[!tip] 在
Linux
系统中,「环境变量」是用来定义系统运行环境的一些参数,比如每个用户不同的家目录(HOME)
、邮件存放位置(MAIL)
等。
变量 | 描述 |
---|---|
HOME | 用户的主目录(也称家目录) |
SHELL | 用户使用的 Shell 解释器名称 |
PATH | 定义命令行解释器搜索用户执行命令的路径 |
EDITOR | 用户默认的文本解释器 |
RANDOM | 生成一个随机数字 |
LANG | 系统语言、语系名称 |
HISTSIZE | 输出的历史命令记录条数 |
HISTFILESIZE | 保存的历史命令记录条数 |
PS1 | Bash解释器的提示符 |
邮件保存路径 |
5.2. 查看
[!warning|style:flat]
¥
是dollor
英文符号
5.3. 创建
终端直接定义变量
[!warning|style:flat]
¥
是dollor
英语符号
[!tip]
- 生效时间: 立即生效
- 生效期限: 当前终端用户,切换用户后失效
- 生效范围:仅对当前用户有效
终端export
定义变量
[!warning|style:flat]
¥
是dollor
英文符号
[!tip]
- 生效时间: 立即生效
- 生效期限: 当前终端,重启终端失效
- 生效范围:所有用户
在~/.bashrc
添加
[!tip]
- 生效时间: 重启终端,或者
source ~/.bashrc
- 生效期限: 永久有效
- 生效范围:仅对当前用户有效
在/etc/environment
添加
[!tip]
- 生效时间: 重启终端,或者
source ~/.bashrc
- 生效期限: 永久有效
- 生效范围:对所有用户有效
6. crontab
定时
6.1. 简介
作用:可以用来让系统定时调用某个指令。
原理:Linux下的任务调度分为两类:系统任务调度和用户任务调度。Linux
系统任务是由 cron (crond)
这个系统服务来控制的,这个系统服务是默认启动的。
注意:crondtab
配置会每分钟刷新一次。
6.2. 配置
配置文件
配置设置
[!tip|style:flat]
*
:取值范围内的所有值/
:一定时间间隔,如分钟字段为*/10
,表示每10
分钟执行1
次-
:某个区间范围,如a - b
表示[a,b]
,
:分散的时间安排,如1,3,4
[!tip|style:flat] 指令配置时,最好写成绝对路径。
参考博客:crontab用法与实例
配置文件编辑
7. 挂载
[!tip]
fs
表示file system
当系统启动的时候,会自动将此文件中指定的文件系统挂载到指定的目录。
Device
要挂载的分区或存储设备Mount point
挂载点filesystem
要挂载设备或是分区的文件系统类型;auto
类型自动搜索,用于cd,DVDparameters
挂载参数dump dump
(0表示不进行dump备份,1代表每天进行dump备份,2代表不定日期的进行dump备份)pass fsck
检测顺序 (其实是一个检查顺序,0代表不检查,1代表第一个检查,2后续.一般根目录是1,数字相同则同时检查)