第一篇 基 础 篇
第1章 计算机体系结构与操作系统
1.1 计算科学与计算机系统
1.1.1 计算科学
-
科学研究手段的演变:
- 在计算机广泛应用之前,理论研究和科学实验是主要的科学研究手段。
- 随着计算机的发明和计算能力的提升,计算分析成为第三种重要的科学研究手段。
-
计算分析的作用:
- 计算分析能够解决许多之前无法解决或不易解决的问题,如复杂的方程或方程组的求解。
- 在实际应用中,如飞机设计,计算分析可以缩短研制周期、降低研制成本。
-
计算科学的定义和发展:
- 计算科学是一个新兴学科,利用先进的计算能力解决复杂的多学科问题。
- 美国计算机协会(ACM)在2005年定义了计算科学,涵盖了从系统设计、分析到应用等多个方面。
-
科学研究的三种手段:
- 理论研究
- 科学实验
- 计算分析
1.1.2 图灵机与计算机系统
图灵机
-
图灵的贡献:
- 图灵被誉为“计算机科学的奠基人”和“人工智能之父”。
- 1966年,ACM设立了“图灵奖”,每年授予在计算机领域作出巨大贡献的科学家。
-
图灵机模型:
- 图灵在1936年发表的《论数字计算在决断难题中的应用》中提出了“图灵机”模型。
- 图灵机由无限延长的纸带、控制器和读写头组成。
- 纸带上的格子包含有限字母表的符号,其中一个特殊符号表示空白。
- 读写头能读出并改变当前格子上的符号,控制器根据当前状态和符号决定下一步动作。
- 图灵机的状态数目有限,有一个特殊状态称为停机状态。
- 图灵机可以模拟人类所能进行的任何计算过程,后来的“丘奇-图灵论题”表明一切合理的计算模型都等同于图灵机。
-
图灵机的影响 :
- 图灵机是一个理想模型,不是具体机器,但诱发了现代通用计算机的产生。
- 现代计算机的主要构成部分可以类比图灵机:纸带相当于存储器,控制器及其状态相当于中央处理器,读写头相当于输入/输出系统。
计算机系统
-
冯·诺依曼简介:
- 美籍匈牙利科学家,生于1903年,卒于1957年。
- 在数学、计算机科学、物理学、化学等领域都有建树。
- 被称为“现代计算机之父”和“博弈论之父”。
-
冯·诺依曼体系结构:
- 提出二进制编码和存储程序等思想,奠定了现代计算机体系结构的基础。
- 计算机结构称为“冯·诺依曼结构”。
- 主要要点:
- 数制采用二进制。
- 程序指令和数据统一存储。
- 计算机按照程序顺序执行。
-
计算机组成:
- 由控制器、运算器、存储器、输入设备、输出设备五部分组成。
- 中央处理器(CPU)由控制器和运算器构成。
- 主存储器中存储程序和数据,CPU按顺序执行指令。
-
冯·诺依曼结构的意义:
- 映射了现实世界的时空观,存储体系对应空间域,指令的顺序执行过程对应时间域。
1.1.3 计算机科学概览
计算机科学源于电子工程、数学和语言学,涵盖算法、计算极限、软硬件及人工智能等。分系统与应用研究,前者关乎计算机自身,含理论、硬件(通用与嵌入式)、软件;后者聚焦各领域应用。Dijkstra称其不仅关乎计算机,还涉应用,且随性能提升,更多用户参与科学计算。
1.2 计算机体系结构的基本概念
计算机体系结构涉及基本理论、原理、设计和技术,包括微体系和网络计算体系结构。本节将介绍摩尔定律、计算机系统层次结构、指令集和存储系统的基本概念。
1.2.1 摩尔定律
- - 1971年,Intel推出全球第一颗通用型微处理器,由2250个晶体管构成。
- - 戈登·摩尔提出“摩尔定律”,即每18个月,芯片上集成的晶体管数量将增加一倍。
- - 2005年之前,主要是单核处理器时代,晶体管数量和CPU频率增长符合摩尔定律。
- - 芯片功率不断增长,散热问题成为障碍,主频每增加1GHz,功耗上升25W,超过150W后,现有散热系统无法满足需求。
- - 芯片温度上升影响可靠性,单纯依靠主频提升系统性能的道路似乎走到尽头。
- - 2005年,摩尔表示摩尔定律可能在未来10至20年内失效。
- - 多核处理器技术出现,使得摩尔定律得以延续。
- - 2005年后,处理器内核数量增多,芯片功率和频率基本不再增长,晶体管数量增长依旧符合摩尔定律。
- - 未来,不断进步的芯片结构和部件可能使摩尔定律依然有效。
1.2.2 计算机系统的层次结构
计算机系统是由软件和硬件组成的一个复杂的有机整体
- 计算机系统的设计不仅仅是硬件或软件单独的工作,而是硬件和软件的紧密协作,形成一个完整的、相互依赖的系统。硬件提供了计算能力和资源,而软件则控制和管理这些资源,提供人机交互的接口。硬件和软件之间的紧密结合是实现高效能和高可用性的基础。
2计算机系统结构设计者所关心的是(机器语言或汇编语言程序员)所看到的计算机结构
- 计算机系统结构设计者(通常是硬件设计师、系统架构师等)在设计计算机系统时,关注的是计算机硬件、指令集架构(ISA)和如何高效执行机器语言或汇编语言程序。设计者需要确保硬件能高效地执行这些底层代码,并为上层的软件提供足够的资源和灵活性。
- 对于机器语言或汇编语言程序员而言,他们直接与硬件交互,必须了解硬件的工作原理和指令集,以便能够编写高效、底层的程序。这些程序通常需要针对具体硬件架构进行优化。
层次 | 名称 | 内容描述 | 关键关注点 |
---|---|---|---|
第0层 | 数字逻辑层 | 处理计算机最基础的硬件电路和逻辑门,如与、或、非等基本逻辑运算。 | 基本的数字电路设计,如加法器、移位器等。 |
第1层 | 微体系结构层 | 描述CPU内部的结构和组织,包含寄存器、算术逻辑单元(ALU)、缓存等硬件组件。 | CPU内部结构设计,流水线和并行处理优化。 |
第2层 | 传统机器层 | 描述机器语言和指令集架构(ISA),即计算机能执行的基本指令集。 | 指令集设计,指令执行的效率,寻址方式和寄存器操作。 |
第3层 | 操作系统层 | 管理硬件资源并为上层提供服务,负责进程管理、内存管理、文件系统、设备管理等。 | 系统资源管理、进程调度、内存分配与回收。 |
第4层 | 汇编语言层 | 汇编语言是机器语言的符号化形式,直接映射到机器指令,通过寄存器操作直接访问硬件。 | 汇编指令的编写、寄存器与内存的直接操作。 |
第5层 | 高级语言层 | 提供更高级的编程抽象,使得程序员可以使用人类易于理解的语法编写程序,最终通过编译器转换为机器代码。 | 编程抽象、平台独立性、编译器优化。 |
第6层 | 应用程序层 | 用户直接交互的程序层,提供各种实际功能,如办公软件、网络应用、多媒体应用等。 | 提供具体应用功能,直接为最终用户服务。 |
1.2.3 指令集
关于计算机指令集和相关概念的表格总结:
序号 | 概念 | 描述 |
---|---|---|
1 | 指令集 | 指令集是计算机系统支持的所有机器指令的集合,它是软硬件之间的分界面。指令集定义了计算机能够执行的所有操作,包括数据传输、算术运算等。 |
2 | 指令格式 | 计算机中最普通的指令格式是:操作码 + 操作数(地址)。指令使用二进制数据表示,操作码指示具体操作,操作数是指操作对象的位置或数据。 |
3 | 指令分类(按操作数数量) | 根据操作数的数量,指令格式可以分为:
![]() |
- 零地址指令 | 操作数由堆栈隐式提供,常见于堆栈式计算机。 | |
- 一地址指令 | 只有一个操作数,通常是一个寄存器或内存地址,另一个操作数由指令隐式提供。 | |
- 二地址指令 | 有两个操作数,操作结果通常存储在其中一个操作数的位置。 | |
- 三地址指令 | 有三个操作数,操作结果存储在其中一个操作数的位置。 | |
- 多地址指令 | 可以有多个操作数,允许更复杂的操作。 | |
4 | 寻址方式 | 按照指令的寻址空间,寻址方式可以分为: |
- 立即数寻址 | 操作数直接嵌入指令中,不需要通过内存或寄存器访问。 | |
- 寄存器寻址 | 操作数位于寄存器中,指令直接指定寄存器。 | |
- 主存寻址 | 操作数位于内存中,指令指定内存地址。 | |
- 堆栈寻址 | 操作数位于堆栈中,通过堆栈指针来访问数据。 | |
5 | 指令功能分类 | 从功能上分类,常见的指令类型包括: |
- 数据传输指令 | 用于在寄存器和内存之间传输数据。 | |
- 算术运算指令 | 执行基本的算术运算,如加法、减法、乘法等。 | |
- 逻辑运算指令 | 执行逻辑运算,如与、或、非等。 | |
- 程序控制指令 | 控制程序的执行流程,如跳转、循环等。 | |
- 输入输出指令 | 用于输入输出操作,如读写硬件设备。 | |
- 处理器控制和调试指令 | 控制处理器的状态或进行调试操作。 | |
6 | 指令集体系结构(ISA) | 指令集因其系统性和复杂性,也被称为指令集体系结构(ISA)。它定义了计算机硬件支持的所有指令以及如何执行这些指令。 |
7 | CISC与RISC | 根据指令系统的复杂程度,ISA可以分为两类: |
- CISC(复杂指令集计算机) | CISC追求强化指令功能,减少程序中的指令数量,从而提高性能。指令较为复杂,能够执行更多的操作。 | |
- RISC(精简指令集计算机) | RISC通过减少指令种类、规范指令格式、简化寻址方式等方式,支持更高效的指令执行和并行处理,适合超大规模集成电路(VLSI)。 | |
8 | CISC与RISC的对比 | - CISC:强化指令功能,减少指令条数,指令复杂,执行速度较慢,但减少了程序的代码量。 |
- RISC:减少指令种类,简化指令集和寻址方式,提高处理器性能,支持并行处理,适合大规模集成电路设计,指令条数较多但每条指令执行较快。 |
1.2.4 存储系统
-
现代通用计算机中存储系统的层次结构
计算机的存储系统分为不同的层次,每一层有不同的速度、容量和成本:- 寄存器组:位于处理器内部,速度最快,但容量最小。用于存储当前正在处理的数据。
- 高速缓冲存储器(Cache):位于CPU与主存之间,用来存储常用的数据和指令,速度较快,容量适中。
- 主存储器(RAM):计算机的主要内存,用于存储运行中的程序和数据,速度适中,但比Cache慢。
- 辅助存储器:如硬盘、SSD等,用于存储程序和数据的持久副本,容量大,速度较慢。
- 脱机存储器:例如光盘、磁带等存储介质,用于长期存储,容量大,但访问速度较慢。
-
程序访问的局部性
程序在执行过程中,常常表现出对某些数据或指令的集中访问特性,这被称为局部性。- 时间局部性:如果程序最近访问了某些数据,它很可能在不久的将来再次访问这些数据。
- 空间局部性:如果程序访问了某个存储位置,那么它很可能会访问相邻的存储位置。这通常在遍历数组或访问连续内存时发生。
-
“Cache-主存-辅存”存储体系
计算机存储体系通常分为三大层级:- Cache :是最接近处理器的存储层,存储着最近使用的数据和指令,速度最快。
- 主存:也叫RAM,存储程序和数据,速度适中。
- 辅存:例如硬盘或固态硬盘,存储大量数据和程序,速度较慢。
- 虚拟存储系统:通过将辅助存储器当作扩展内存使用,虚拟存储管理技术使计算机能够访问比实际物理内存更多的内存。
-
“Cache-主存”层次的理论依据
Cache和主存之间的层次结构是基于程序的 局部性理论,即程序常常会反复访问某些数据,特别是时间局部性和空间局部性,这使得Cache的设计有意义。Cache通过存储这些“热点”数据,减少对较慢主存的访问。 -
Cache与主存储器间的地址映射方式
由于Cache空间通常比主存小得多,如何将主存数据高效地映射到Cache是一个关键问题。常见的映射方式有:- 全相联映射 :任何主存块可以映射到Cache的任何位置。灵活但查找速度慢。
- 直接映射:每个主存块只能映射到Cache的一个特定位置。简单高效,但可能会造成Cache冲突。
- 组相联映射:结合了全相联映射和直接映射的特点,将Cache分为若干组,每个主存块只能映射到特定组中的某个位置。
-
Cache替换算法
当Cache已满而需要存入新数据时,需要选择替换掉Cache中的某些数据块。常见的替换算法有:- 随机法(RAND):随机选择一个Cache块进行替换。简单但可能导致效率低下。
- 先进先出法(FIFO):最早加载到Cache的数据会最先被替换。
- 最近最少使用法(LRU):选择最长时间未使用的Cache块进行替换。该算法能够较好地利用局部性原则。
-
Cache读写过程中的数据一致性问题
数据一致性是指在多个地方存储同一数据时,这些存储副本应保持一致。- Cache和主存之间的数据一致性:当处理器更新Cache中的数据时,必须确保主存中的数据也随之更新。
- 不同处理器核心之间的Cache一致性:在多核处理器中,每个核心都有自己的Cache,必须确保各核心的Cache中同一数据保持一致。
-
Cache与主存之间的数据一致性维护方式
为了保持Cache与主存的一致性,采用以下两种写操作方式:- 写直达(write through):每次写操作都会同时更新Cache和主存,确保两者数据一致。
- 写回(write back):数据首先写入Cache,只有当数据被替换出Cache时才更新主存,这减少了写操作的频率,提高了性能。
-
多核处理器中的缓存一致性协议
在多核处理器中,每个核心可能有自己的Cache,必须通过 缓存一致性协议来保证不同核心Cache中的数据一致。- MESI协议(Modified, Exclusive, Shared, Invalid):用于多核处理器的经典缓存一致性协议。每个Cache Line(存储单元)有四种可能的状态:
- 修改(Modified):数据已被修改,且仅在当前Cache中存在。
- 独占(Exclusive):数据只在当前Cache中,且没有被修改。
- 共享(Shared):数据可以在多个Cache中共享。
- 失效(Invalid):数据无效。
- MESI协议(Modified, Exclusive, Shared, Invalid):用于多核处理器的经典缓存一致性协议。每个Cache Line(存储单元)有四种可能的状态:
-
虚拟存储系统
虚拟存储系统是一种技术,它使得程序能够使用比物理内存更多的内存空间。通过虚拟内存,计算机将主存与辅存结合使用,虚拟存储系统使得操作系统能够管理内存的分配和交换,从而扩大计算机能够使用的内存空间。
- 虚拟存储管理技术:通过将主存与辅存结合,动态地将主存中不常用的部分转存到辅存,优化内存的使用。
1.3 微处理器体系结构
1.3.1 单核处理器基本结构
-
CPU的组成部分:
- 控制器:负责指挥和控制计算机系统的各个部件,执行指令并协调操作。
- 运算器:执行数据加工处理等操作,核心部件是算术逻辑单元(ALU)。
- 存储单元:包括高速缓存和寄存器组,用于暂时存放数据,提高处理速度。
-
指令集:
- 不同的指令集会导致不同的处理器设计,如Intel的复杂指令集和ARM的精简指令集,但基本组成和工作原理相似。
-
CPU的逻辑结构:
- 图展示了CPU的逻辑结构,主要由控制器、运算器和存储单元三部分组成,通过内部总线相连。
-
寄存器的作用:
- 寄存器组用于暂时存放数据,访问速度比内存快,可以减少CPU访问内存的次数,从而提高处理速度,但由于芯片面积和集成度的限制,寄存器组的容量有限。
1.3.2 多核处理器基本结构
-
微处理器性能提高的因素:
- 半导体工艺技术的飞速进步和体系结构的不断发展。
- 体系结构的进展在半导体工艺技术发展的基础上进一步提高了微处理器的性能。
-
多核处理器的应用:
- 处理器芯片厂商通过提高主频来提升性能,但面临瓶颈,转而采用多核设计。
- 多核处理器满足了日益复杂的多媒体、科学计算、虚拟化等应用领域对计算能力的需求。
-
多核处理器的结构特点:
- 通用处理器芯片大多采用多核处理器(如Chip Multi-Processor, CMP),具有4核、8核等配置。
- CMP可分为同构多核和异构多核,同构多核处理器内部结构相同,异构多核处理器内部结构不同。
- CMP的各CPU核心之间需要数据共享与同步,通信机制是其高性能的重要保障,主要有总线共享Cache结构和片上互联结构两种。
- 总线共享Cache结构简单,通信速度快,但可扩展性较差。
- 片上互联结构各CPU核心独立,通信灵活,但结构复杂,软件改动较大。
1.3.3 指令的执行
一、指令执行过程
计算机指令执行是计算机完成任务的基础过程,涉及多个阶段。指令执行过程通常分为五个阶段:
阶段 | 作用 |
---|---|
取指令(IF) | 程序计数器(PC)存储下一条要执行指令的地址。CPU根据PC的值从主存中取出指令,并将指令存储在指令寄存器中。取指令后,PC自动递增,指向下一条指令的地址,准备取下一条指令。 |
指令译码(ID) | 在这一阶段,CPU对取到的指令进行解析,分解为操作码和操作数部分,识别指令类型及操作数据的方式。不同控制方式(如硬件控制或微程序控制)决定了指令如何解码。 |
执行指令(EX) | 指令执行的核心阶段。ALU(算术逻辑单元)根据指令类型执行算术或逻辑运算,或进行地址计算等操作。这一阶段的输出通常是一个计算结果或一个新的内存地址。 |
访存取数(MEM) | 根据指令的需求,CPU访问内存进行数据读取或存储。若指令要求读取或写入数据到主存,这个阶段会完成这一操作。 |
结果写回(WB) | 指令执行完后,将结果写回CPU的寄存器或主存。部分指令可能会更新程序状态寄存器中的标志位,如修改零标志位、溢出标志位等。 |
一个完整的指令周期包含以上几个阶段,而每个阶段通常会涉及多个CPU周期 ,每个CPU周期又由多个时钟周期组成。时钟周期是系统最基本的时间单位,CPU的时钟频率决定了时钟周期的长度,时钟频率越高,单位时间内的时钟周期数越多,计算机处理能力越强。
二、优化技术
随着计算机技术的发展,为了提高指令执行的效率,现代微处理器采用了多种优化技术。以下是常见的几种优化方法:
技术 | 原理 |
---|---|
流水线 | 将指令执行过程分解为多个独立的阶段,各个阶段可以并行工作。多个指令可以同时在不同阶段执行,提高吞吐量,减少指令执行的空闲时间。例如,在取指阶段时,其他指令可以在不同阶段并行运行。 |
分支预测 | 处理器在遇到条件分支指令时,会根据历史数据或算法预测程序可能执行的路径。如果预测正确,处理器可以避免等待分支判断完成,从而提高程序执行效率。减少分支指令引发的“停顿”。 |
乱序执行 | 允许处理器不按顺序执行指令,而是根据指令所需资源和数据的可用性进行调度。改变指令执行顺序,最大化利用CPU资源,减少资源等待时间,从而提高处理器整体效率。 |
超标量 | 处理器在一个时钟周期内可以同时执行多条指令,拥有多个执行管道,在同一个时钟周期内发射并执行多个指令。需要指令调度器合理安排,确保指令之间没有冲突。 |
超长指令字(VLIW) | 在一个指令中包含多个操作码和操作数,允许多个操作同时进行。通过编译器优化与调度,实现指令级并行,提高程序并行性,依赖编译器安排指令的执行顺序和并行度。 |
向量指令 | 向量指令通过一次性处理多个数据元素来提升处理效率,特别适用于大规模数据并行计算。通过一次操作处理多个数据点,适用于科学计算、图像处理等任务。 |
1.4 操作系统的基本概念
1.4.1 操作系统的定义和作用
计算机系统的资源按照其作用可大致分为四类:处理器、存储器、I/O设备和文件。
内容 | 描述 |
---|---|
计算机系统组成 | 计算机系统由硬件和软件组成,硬件包括处理器、存储器和各种输入/输出设备,软件通常以进程和文件的形式存在。 |
操作系统的作用 | |
用户视角 | 操作系统为用户提供更好的服务,构建和谐的交互环境,简化用户操作,提供可靠和安全的服务管理。 |
系统视角 | 操作系统作为资源管理者,负责分配和管理计算机系统中的各种软硬件资源。 |
操作系统提供的服务 | |
程序开发 | 提供编辑器和调试器等工具。 |
程序运行 | 处理程序运行的步骤和资源调度。 |
I/O设备访问 | 提供统一的接口,隐藏设备细节。 |
文件访问 | 管理文件存储设备特性和数据组织结构。 |
系统资源访问 | 管理所有资源,提供保护和访问控制。 |
错误检测和响应 | 处理各种错误,最小化对应用程序的影响。 |
日志服务 | 收集统计数据,监控性能参数,记录用户日志,提高系统性能。 |
1.4.2 操作系统的基本特征
特性 | 定义 | 实现方式/优势 |
---|---|---|
并发(Concurrency) | 操作系统中多个事件在同一时刻或时间段内发生。 | - 多道程序:多个程序在同一处理器上交替执行。
- 多处理器/多核系统:多个程序在不同处理器上并行执行。 优势:提高系统资源的利用率和运行效率。 |
共享(Sharing) | 操作系统支持资源共享,使多个进程能够同时使用相同的资源。 | - 互斥共享:多个进程不能同时访问某一资源。
- 同时访问:多个进程可以同时访问资源。 优势:提高资源利用率。 |
虚拟(Virtualization) | 通过将物理实体映射为逻辑上的对应物,为用户提供虚拟的硬件环境。 | - 常见技术:虚拟处理器、虚拟存储器、虚拟外部设备。
优势:多个用户或进程可以高效共享系统资源,增强灵活性和资源利用率。 |
异步(Asynchrony) | 事件的发生和处理不需要严格按照时间顺序进行。 | - 进程或线程可以在等待某个操作完成的同时继续执行其他任务。
优势:提高响应速度和资源利用率,广泛应用于I/O操作、任务调度和事件驱动编程等领域。 |
1.5 操作系统的基本功能和原理
计算机系统由硬件(如处理器、存储器和输入输出设备)和软件(如磁盘文件和应用程序)组成。操作系统管理这些资源,为用户提供易操作平台。
操作系统的主要功能包括:处理器管理、存储管理、设备管理、文件管理和作业管理。
现代操作系统增加了其他功能,如网络通信管理和系统安全性。这五大功能之间的关联日益紧密,界限模糊。例如,进程管理既属于处理器管理,也涉及作业管理。因此,有些操作系统教程可能只介绍前四大功能,而不提及作业管理。
1.5.1 处理器管理
1. 处理器管理功能
1.1 中断处理
1)指令类型
1. 特权指令:仅操作系统内核可以执行,用于进行敏感操作(如修改寄存器、启动设备等)。
2. 非特权指令:所有程序都可以执行的指令。
2)处理器的运行状态
1. 内核态:能够执行所有指令,拥有较高的权限。
2. 用户态:仅允许执行非特权指令,权限较低。
3)用户态切换到内核态的三种方式
1. 系统调用:用户程序请求操作系统服务时触发。
2. 异常:程序运行过程中发生错误或异常时触发。
3. 外围设备中断:外部设备请求时触发。
1.2 中断概念延伸
中断是指CPU对系统中发生的事件做出的反应,它暂停当前程序的执行,保存现场后执行相应的中断处理程序。处理完后,若进程优先级最高,则返回断点继续执行。
1.3 中断类型
按功能,中断源可以分为五类:
1. 机器故障中断:反映硬件故障(如电源故障、内存错误等)。
2. I/O中断:外部设备操作完成后产生的中断(如打印机完成打印、磁盘传输完成等)。
3. 外部中断:外部事件触发的中断(如计时器到时、外部信号等)。
4. 程序性中断:程序错误引发的中断(如非法操作码、无效地址、运算溢出等)。
5. 访管中断:由执行“访问管理程序”指令引发的中断,使CPU状态从用户态切换到内核态,操作系统根据编号处理请求。
1.4 访管中断
在配置了通道的计算机系统中,用户程序进行I/O操作时会触发访管中断,使CPU状态从用户态切换到内核态,由操作系统处理I/O资源的使用请求。
2. 进程管理
2.1 进程定义
进程是计算机中程序在某数据集上的一次运行活动,是操作系统进行资源分配和调度的基本单位。
2.2 进程与程序的区别
1. 进程:动态的概念,具有并发特性,具有生命期,存在于计算机运行期间。
2. 程序:静态的概念,不具有并发性,可以长期存在于外存上。
2.3 进程与程序的关系
一个程序可以对应多个进程,进程是程序在不同数据集上的执行实例。
2.4 进程控制块(PCB)
进程控制块是操作系统管理进程的核心数据结构,是进程存在的唯一标志,包含进程的状态、程序计数器、寄存器值等信息。
2.5 线程
线程是操作系统调度和执行的最小单位。线程是进程的子单位,一个进程中可以并发多个线程,每个线程执行不同的任务。
2.6 进程状态及状态转换
1. 基本状态
1. 运行态 (Running):当前正在CPU中执行的进程。
2. 就绪态 (Ready):等待CPU资源的进程。
3. 等待态 (Waiting):进程因等待某些资源而被阻塞。
2. 其他状态
1. 新建态 (New):刚被创建的进程。
2. 终止态 (Exit):执行完毕或被终止的进程。
3. 进程状态转换
进程会根据不同条件在这些状态之间转换。例如,从**就绪态**到**运行态**,或者从**运行态**到**等待态**。
2.7 进程就绪状态
当进程获得了除了CPU以外的所有资源后,处于**就绪态**,等待CPU资源以开始执行。
1.5.2 存储管理
知识点 | 内容 |
---|---|
用户源程序变为可执行程序的步骤 | |
编译:将用户源代码(如C语言代码)转换为机器语言的目标代码。编译器进行语法检查,生成中间代码或汇编语言文件。 | |
链接:将多个目标文件与库文件链接成一个可执行文件。链接器解析符号,确保各个模块的符号地址正确并生成最终的可执行程序。 | |
装入:将最终生成的可执行文件加载到内存中,分配必要的内存空间,进行地址转换并准备执行。装入程序确保程序的指令和数据段正确地加载到内存中。 | |
存储器管理的主要功能 | |
内存空间的分配与回收:操作系统负责动态地为进程分配内存,并在进程执行完毕后回收内存空间。可以是静态分配(编译时)或动态分配(运行时)。 | |
地址转换:操作系统通过虚拟内存技术将虚拟地址转换为物理地址,使得程序可以使用比物理内存更大的地址空间。 | |
内存空间的扩充:通过虚拟内存,操作系统可以利用硬盘作为扩展内存,增加系统可以使用的内存容量。 | |
存储保护:操作系统通过内存保护机制(如页表、段表)保护各个进程的内存空间不被其他进程访问,确保系统的稳定性和安全性。 |
1.5.3 设备管理
功能类别 | 具体职责 |
---|---|
设备分配与管理 | - 将外部设备分配给请求使用该设备的进程。
- 设备回收,确保设备可供其他进程使用。 |
I/O通信处理 | - 处理CPU与设备间的数据交换。
- 调度I/O请求,确保设备高效运行。 |
中断响应 | - 响应设备中断请求,处理中断并决定如何响应。 |
设备状态维护 | - 维护设备状态,确保设备资源的合理利用。
- 处理设备故障,保证系统稳定。 |
总结 | 设备管理模块通过分配设备、处理I/O通信、响应中断和维护设备状态,确保外部设备与处理器的高效交互与稳定运行。 |
1.5.4 文件管理
功能模块 | 描述 |
---|---|
文件系统 | 负责文件的逻辑组织与物理组织、目录结构的管理、文件的存取控制与安全管理等。 |
文件逻辑组织 | 文件在文件系统中的组织方式,包括如何定义文件的名称、类型、大小及其关系等。 |
文件物理结构 | 存储文件的方式,常见的有: |
- 顺序结构:文件内容按顺序存储,简单但容易产生碎片。 | |
- 链表结构:文件由多个数据块通过指针连接,灵活性高,但访问速度较慢。 | |
- 索引结构:文件由索引块管理,便于快速访问,解决了顺序和链表结构的缺点。 | |
目录结构 | 文件系统中的目录结构用于组织文件,使得用户能够快速地定位文件。常见的目录结构有: |
- 单级目录:只有一个目录,所有文件存储在其中,不利于管理。 | |
- 多级目录:按层次组织文件,便于管理,广泛应用。 | |
文件存取控制 | 对文件的访问进行权限管理,确保文件的安全性。包括文件的读写权限和执行权限等。 |
文件系统的管理 | - 文件分配:通过不同的分配方式(顺序、链式、索引)管理文件的数据块。 |
- 文件备份与恢复:定期备份文件以防止数据丢失,提供文件恢复机制。 | |
- 文件压缩:压缩文件以节省存储空间,提高传输效率。 | |
文件存储格式 | 文件的存储类型,常见的有: |
- 文本文件:存储为可读文本格式,方便编辑和查看。 | |
- 二进制文件:存储为机器可读格式,一般用于程序或数据。 | |
常见文件系统类型 | 不同操作系统使用不同的文件系统,常见的有: |
- FAT:适用于小型存储设备,常见于U盘等设备。 | |
- NTFS:Windows系统常用,支持大文件和高效的文件权限控制。 | |
- EXT:Linux系统常用文件系统,适用于大容量存储,支持高效存储管理和文件权限控制。 | |
总结 | 文件系统负责文件的管理,包括文件的逻辑与物理组织、目录结构、存取控制、备份等,确保文件高效、安全地存储和访问。 |
1.5.5 作业管理
功能模块 | 描述 |
---|---|
作业管理 | 用户在计算过程中或事务处理中要求计算机系统所作工作的总和,作业是计算机系统提交任务的基本单位。 |
作业组成 | 作业包括输入、输出、调度和控制等。 |
作业生命周期 | 一个作业从交给计算机系统到执行结束退出系统,通常经历四个状态: |
- 提交状态:作业被提交到计算机系统,等待调度。 | |
- 后备状态:作业被放入等待队列,等待获得CPU资源。 | |
- 执行状态:作业获得CPU资源开始执行。 | |
- 完成状态:作业执行结束,退出系统,释放资源。 | |
作业调度与控制 | 作业调度负责将作业从后备队列调度到执行状态,作业控制则用于管理作业的执行顺序与优先级,确保资源的高效利用。 |
作业输入与输出 | 作业的输入是计算任务的初始数据,作业的输出是计算结果或事务处理的结果,通常通过I/O设备进行输入输出。 |
作业优先级与排队 | 作业调度策略决定作业执行的优先级,优先级高的作业会先执行。作业排队策略可以根据作业类型、大小等因素进行优化。 |
总结 | 作业是计算机系统中的基本任务单位,管理作业的调度、控制、输入输出等环节,保证作业的高效执行和系统资源的合理分配。 |
练习题
第2章 Linux系统概述
Linus Torvalds 负责开发的Linux只是一个内核。内核指的是一个提供设备驱动、文件系统、进程管理、网络通信等功能的系统软件,内核并不是一套完整的操作系统,只是操作系统的核心。
2.1 Linux系统的发展历程
时间 | 事件 |
---|---|
1991年 | Linus Torvalds首次发布Linux内核,开源并自由发布。 |
1992年 | Linux内核得到改进,开始与GNU工具集结合,形成了一个完整的操作系统。 |
1994年 | Linux内核2.0版本发布,支持多处理器架构,标志着Linux的商业化发展。 |
2000年 | Linux逐步走向成熟,企业级应用逐步增加,特别是在服务器和嵌入式系统中。 |
2005年及之后 | Linux成为开源运动的标志,全球范围内广泛应用,并成为Android等操作系统的基础。 |
2.2 常用Linux系统版本
版本 | 描述 |
---|---|
Ubuntu | 基于Debian的Linux发行版,强调易用性,适合桌面用户和开发人员。 |
CentOS | 基于Red Hat Enterprise Linux(RHEL)的社区版本,广泛应用于服务器环境。 |
Debian | 稳定的Linux发行版,广泛用于开发和生产环境,提供广泛的软件包和可靠的系统更新。 |
Fedora | 由Red Hat主导开发,强调最新技术和开源理念,适合开发人员和技术爱好者。 |
Red Hat Enterprise Linux (RHEL) | 企业级Linux发行版,提供企业级支持,适合商业应用。 |
2.3 Linux系统特征
特征 | 描述 |
---|---|
开源与自由 | Linux内核和大多数应用程序是开源的,允许用户自由使用、修改和分发。 |
多任务支持 | 支持同时运行多个进程,提供多用户、多任务的环境。 |
稳定性和可靠性 | Linux以其稳定性、长时间的运行能力和低资源消耗而著称。 |
安全性强 | 具备强大的权限管理和访问控制,内置多层安全机制,适合企业和关键任务的环境。 |
广泛的硬件支持 | 支持多种硬件架构和平台,从个人计算机到大型服务器和嵌入式设备都能运行Linux系统。 |
2.4 Linux系统的应用与前景
领域 | 应用 |
---|---|
服务器应用 | Linux是全球最流行的服务器操作系统,广泛应用于Web服务器、邮件服务器和数据库服务器等领域。 |
嵌入式系统 | 在嵌入式设备如路由器、智能电视、汽车系统中,Linux操作系统有着广泛的应用。 |
云计算与大数据 | Linux是许多云计算平台和大数据解决方案的基础,提供高效的虚拟化支持和容器管理。 |
移动设备与Android | Android操作系统基于Linux内核,广泛应用于智能手机、平板电脑和其他智能设备。 |
前景 | 随着开源软件的发展和Linux系统在各领域应用的扩展,Linux的前景非常广阔,尤其在云计算、物联网和AI等新兴领域。 |
练习题
第3章 Linux系统使用基础
3.1 Linux系统的安装
3.2 桌面环境
小节 | 描述 |
---|---|
3.2.1 KDE | KDE(K Desktop Environment)是一个自由和开源的桌面环境,提供一个灵活且美观的界面。其界面类似于Windows,适合喜好高度定制的用户。 |
3.2.2 GNOME | GNOME是一个简单、现代化且易用的桌面环境,专注于简洁和用户友好的设计。它适合喜欢简约和高效操作体验的用户。 |
3.2.3 统一 | 统一的桌面环境设计指的是通过一致的用户界面和行为规范,使不同Linux发行版之间的使用体验更加一致,用户可以在不同的环境中有相似的操作感受。 |
3.2.4 配合 | 配合是指桌面环境与Linux操作系统的其他部分(如系统工具、应用程序)紧密集成,提供无缝的用户体验。不同的桌面环境在Linux系统中可以互相配合使用,以优化性能和用户体验。 |
3.2.5 肉桂 | 肉桂(Cinnamon)是一个现代化且高度可定制的桌面环境,适合喜欢传统桌面布局(类似Windows)的用户。它注重易用性和高效性。 |
3.2.6 适用于低配置硬件设备的Linux桌面环境 | 针对低配置硬件设备(如旧电脑或资源受限设备)的Linux桌面环境包括LXDE、Xfce,Fluxbox,JWM,Fvwm,fvwm95等。这些桌面环境资源消耗小,提供流畅的用户体验。 |
3.3 常用Linux命令
3.3.1 Linux命令的基本格式
基本格式:
命令 [选项] [参数]
-------------
命令:是执行的核心操作,例如 ls、cd、echo 等,指示操作系统执行特定任务。
选项:用于修改命令的默认行为,通常以短横线 - 开头(单个字母用-,单词用--)。
参数:提供给命令的对象,通常是文件、目录或其他资源,命令通过参数来指定要操作的对象。
[]表示这部分是选择内容,可有可无。
--------------
比如:
ls显示当前目录中的文件
ls -l 详细的显示文件
ls -l liye.txt 详细的显示liye.txt这个文件
当我们进入shell(在图形化界面:开始菜单—应用程序—附件—终端打开)后会看到
当然还有#(表示命令提示符,表示等级用到如果是#号就表示你是超级用户,如果是$就是说你是普通用户),@(没什么意思就是分隔用的)
~(主目录也叫家目录):root家目录在/root下,其它的用户在/home/[一般是用户名]下。
3.3.2 Linux简单命令
ls
:列出目录内容
ls [选项] [目录]
默认列出当前目录的内容。
常见选项:
-l:以长格式显示详细信息(如权限、大小、修改时间)。
-a:显示所有文件,包括以 . 开头的隐藏文件。
-h:与 -l 结合使用,显示人类可读的文件大小(如 KB, MB)。
cd
:更改目录
cd [目录]
默认返回到用户的家目录 ~。
cd ..:切换到上一级目录。
cd /:切换到根目录。
cd [当前层含义的目录名]:到当前层下的目中
cd ../[目录]:表示到上一层目录下的对应目录
pwd
:显示当前目录
pwd
没有其他用法
passwd
:修改用户密码(书中提到了前两个)
passwd
修改当前用户的密码,系统会要求输入当前密码并设置新密码。
passwd [用户名]
修改指定用户的密码,需超级用户权限。
passwd -x [天数] [用户名]
设置密码的最大使用期限。例如,设置密码在 30 天后过期。
passwd -i [天数] [用户名]
设置密码过期后,用户可以在过期后多少天内重新登录。
passwd -l [用户名]
锁定指定用户的密码,用户无法使用密码进行登录。
passwd -u [用户名]
解锁已锁定的用户密码,恢复用户的登录权限。
passwd -d [用户名]
删除指定用户的密码,用户无法使用密码进行登录,但如果没有其他认证机制,仍然可以登录。
passwd -e [用户名]
强制用户在下次登录时更改密码。
passwd -n [天数] [用户名]
设置用户在设置新密码后的最短使用时间,防止频繁修改密码。
w
:显示登录用户信息(记第一个w的用法就可以了)
w
命令用于显示系统中当前登录的用户信息和他们的活动情况。
w -h
去掉表头,简洁输出(只显示用户信息)。
w -u
仅显示当前用户的信息。
w -f
显示用户的活动信息,但忽略来自其他终端的信息。
w [用户名]
显示特定用户的活动信息。
输出内容
USER 列显示当前登录用户。
TTY 显示登录终端。
FROM 显示用户的来源地址。
LOGIN@ 显示登录时间。
IDLE 显示空闲时间。
JCPU 显示该用户的 CPU 时间总和。
PCPU 显示当前进程的 CPU 时间。
WHAT 显示当前用户正在执行的命令。
who
:显示当前登录的用户信息
who
和w类似,不过显示当前登录到系统的用户信息
echo
:显示消息或变量值
echo [文本或变量]
echo -e "这将支持转义字符,-e"
echo -n "取消文末换行"
当然有一些不用-e也支持,但具体看shell版本型号。
常见的转义字符:(\[源字符]就是转义字符)
为什么会有转义字符,比如【"双引号长这样"。",系统认为是两个"内是一起的】
【与我们告诉系统\后面的符号没有任何功能只是一个符号】
\n:换行
\t:制表符(Tab)
\\:反斜杠(\)
\":双引号(")
\':单引号(')
\a:响铃(终端发出声音)
\b:退格
\r:回车
\v:垂直制表符
\f:换页
\0xxx:按照八进制ascii表输出字符
\xhh:按照十六进制ascii表输出字符
date
:显示或设置系统日期和时间(了解前四个)
选项 | 描述 | 参数格式 | 示例 | 输出 |
---|---|---|---|---|
无选项 | 显示当前日期和时间 | 无 | date
| Thu Feb 25 12:34:56 UTC 2025
|
+FORMAT
| 按指定格式显示日期和时间 | +%FORMAT
(如 %Y-%m-%d %H:%M:%S )
| date "+%Y-%m-%d %H:%M:%S"
| 2025-02-25 12:34:56
|
-d
| 显示指定日期时间的格式化输出 | "date_string" (如 "2025-02-25")
| date -d "2025-02-25"
| Thu Feb 25 00:00:00 UTC 2025
|
-s
| 设置系统日期和时间 | "YYYY-MM-DD HH:MM:SS"(有空格)
| sudo date -s "2025-12-31 12:00:00"
| (没有输出,系统时间更新) |
-u
| 显示UTC时间 | 无 | date -u
| Thu Feb 25 12:34:56 UTC 2025
|
-R
| 显示RFC-2822格式的日期 | 无 | date -R
| Thu, 25 Feb 2025 12:34:56 +0000
|
-I
| 显示ISO 8601格式的日期 | 无 | date -I
| 2025-02-25 |
-f
| 从文件中读取日期并显示 | FILE_NAME (包含日期的文件)
| date -f datefile.txt
| 根据文件中的内容输出日期 |
-t
| 输出格式化的日期,不显示额外信息 | +FORMAT (如 %H:%M:%S )
| date -t "+%H:%M:%S"
| 12:34:56 |
3.4 软件包
3.4.1 Linux源码包(安装过程在后续的命令中,目前只要了解就好)
定义:
Linux源码包是指包含了软件的源代码及必要的编译文件、依赖库和配置文件的压缩包。源码包通常需要用户手动编译、配置和安装。
特点:
- 可定制性高:用户可以根据需要修改源码进行定制,优化编译选项。
- 较复杂的安装过程:需要解压源码并进行配置、编译和安装。一般需要具备编译环境。
- 适用于特定需求:适合需要根据硬件环境或个性化需求修改和优化的用户。
优缺点:
- 优点:高度可定制,适合对软件有特定要求的用户。
- 缺点:安装过程繁琐,且对于不熟悉编译过程的用户较为复杂。
3.4.2 Linux二进制包
定义:
Linux二进制包是经过编译后的软件包,可以直接在目标系统上安装和运行。二进制包已准备好,用户只需下载并安装。
特点:
- 安装过程简单:与源码包不同,用户无需编译,直接安装。
- 较少的定制性:由于是编译后的程序,用户无法修改或优化编译选项。
- 较高的兼容性:适用于多数常见的Linux发行版,安装过程中无需过多配置。
常见的二进制包格式:
- RPM(Red Hat Package Manager):主要用于Red Hat及其衍生版本(如CentOS、Fedora)。
- DEB(Debian Package):主要用于Debian及其衍生版本(如Ubuntu)。
优缺点:
- 优点:安装快速,便于普通用户使用,省去了编译和配置的步骤。
- 缺点:缺乏定制性,无法对程序进行个性化配置。
3.5 软件安装、运行与卸载(也可以用yum但是书上是rpm所以不做yum的介绍)
rpm包格式:<包名>-<版本号>-<发行号>.<架构>.rpm
包名(<包名>)
包名是软件包的名称,通常与软件的实际名称一致。例如,httpd、nginx、vim 等。
版本号(<版本号>)
版本号表示软件的发布版本。例如,2.4.6、1.0.0、5.1.2 等。
发行号(<发行号>)
发行号是为同一版本的软件包的不同构建或发布提供区分的标识。它用于标识该版本的不同构建版本,特别是在进行修复或更新时,可能会改变发行号。例如,1、2、el7(表示为特定操作系统版本进行构建)等。
架构(<架构>)
表示该软件包适用的硬件架构。常见的架构有:
x86_64:64位的x86架构(适用于大部分现代的桌面和服务器)
i386:32位的x86架构(较老的硬件)
armv7l:适用于ARM架构的设备
aarch64:适用于64位ARM架构的设备
文件扩展名(.rpm)
.rpm 是该包的文件扩展名,标识它是一个RPM包文件。
3.5.1 RPM包安装、卸载和升级
RPM包管理概述:
RPM(Red Hat Package Manager)是Linux中常用的一种软件包管理工具,适用于Red Hat、CentOS、Fedora等发行版。通过RPM,可以方便地安装、升级、卸载软件包。
命令 | 选项 | 参数 | 作用 |
---|---|---|---|
rpm -e | -e :卸载
| [包名]
| 卸载指定的软件包 |
--nodeps
:不检查依赖关系
| 卸载时不检查依赖关系 | ||
rpm -Uvh | -U :安装或升级
| [包全名]
| 安装或升级软件包,若已安装则升级至最新版本 |
-v :显示更详细信息
| 显示详细信息 | ||
-h :显示进度
| 显示安装进度条 | ||
rpm -Fvh | -F :强制升级
| [包全名]
| 仅当当前版本较低时进行升级,若未安装则不执行 |
-v :显示详细信息
| 显示详细信息 | ||
-h :显示进度
| 显示安装进度条 | ||
rpm -ivh | -i :安装
| [包全名]
| 安装指定的 RPM 包 |
-v
:显示更详细信息
| 显示详细信息 | ||
-h :显示进度
| 显示安装进度条 |
3.5.2 软件包的查询
RPM包查询功能
:
RPM工具不仅可以用来安装、卸载和升级软件包,还可以查询已安装或未安装的包。
命令 | 选项 | 参数 | 作用 |
---|---|---|---|
rpm | -q :查询
| [包名]
| 查询指定的软件包是否已安装 |
-a :所有
| 查询系统中所有已安装的 RPM 包 | ||
rpm -qi | 无 | [包名]
| 显示指定软件包的详细信息 |
rpm -qip | -p :查询未安装包
| [包全名]
| 查询未安装的软件包详细信息 |
rpm -ql | -l
:列出文件
| [包名]
| 列出已安装包中的所有文件及其安装位置 |
rpm -qlp | -p :未安装包的文件
| [包全名]
| 列出未安装包中的所有文件及其将被安装的位置 |
rpm -qf | -f :查询文件所属包
| [文件路径]
| 查询指定文件属于哪个已安装的 RPM 包 |
rpm -qR | -R
:依赖关系
| [包名]
| 查询指定软件包的依赖关系 |
rpm -qRp | -p :查询未安装包的依赖关系
| [包全名]
| 查询未安装包的依赖关系 |
补充说明
systemctl
【选项】start 【参数】<服务名> :启动指定的服务
【选项】stop 【参数】<服务名> :停止指定的服务
【选项】restart 【参数】<服务名> :重启指定的服务
【选项】status 【参数】<服务名> :查看指定服务的状态
【选项】enable 【参数】<服务名> :设置服务开机自启
【选项】disable 【参数】<服务名> :禁用服务开机自启
【选项】--type=service 【参数】无 :查看所有已启用的服务
【选项】--all --type=service 【参数】无 :查看所有服务的状态
journalctl
【选项】-u 【参数】<服务名> :查看指定服务的日志
service(书上是用的这个)
【选项】start 【参数】<服务名> :启动指定的服务
【选项】stop 【参数】<服务名> :停止指定的服务
【选项】restart 【参数】<服务名> :重启指定的服务
【选项】status 【参数】<服务名> :查看指定服务的状态
1. RPM包来源
官方源:操作系统官方仓库。
第三方源:外部供应商发布的包。
本地包:本地下载或生成的RPM包。
2. 依赖性管理
yum/dnf:自动解决包的依赖问题,推荐使用它们安装RPM包。
3. RPM包签名
可以验证RPM包的数字签名来确保包未被篡改:
rpm --checksig <package.rpm>
4. 查看RPM包内容
列出包中的文件:rpm -ql <package_name>
查询某文件属于哪个包:rpm -qf <file_path>
5. 创建自己的RPM包
使用 rpmbuild 创建RPM包。
6. 卸载包时依赖问题
使用 --nodeps 强制卸载包,忽略依赖关系:rpm -e --nodeps <package_name>
7. RPM包日志
查看安装日志:/var/log/yum.log 和 /var/log/dnf.log
8. 与其他包管理系统对比
DEB包:与RPM包不同,适用于Debian/Ubuntu系统。
9. RPM与容器
可以在容器镜像中使用RPM包来部署应用程序。
练习题
第4章 shell脚本编程基础(建议最后看)
第4章涉及了 shell 脚本编程的基础知识。下面我帮你梳理一下这个大纲的主要内容和要点。简单说一下,三级应该不难,如果我考过了,会回来修改难度的。(2025年2月24日10:27:37)
4.1 shell编程概述
shell本身是一个用C语言编写的程序,是连接 用户 和 UNIX/Linux内核 的桥梁。
#!/bin/bash , “#!” 说明该脚本使用哪种shell编写的,通常放在脚本第一行,从而调用相应的解释程序予以执行
Linux中,创建文件默认是不可执行的文件,需要修改文件的权限,为文件增加可执行权限(chmod u+x 文件名),后在命令行模式下直接输入该文件的相对路径 ./文件名,即可运行
4.1.1 什么是shell
- Shell 是用户与操作系统之间的接口,允许用户与操作系统交互。它是命令行环境的一个程序,负责解释用户输入的命令。
- 常见的 Shell 有 Bash、Zsh、Csh 等,它们提供了一种编程语言来自动化执行系统任务。
4.1.2 shell的种类(可以通过cat /etc/shells)
- Bash(Bourne Again Shell):最常用的 shell,功能强大,兼容 Bourne Shell(sh)。
- Zsh(Z Shell):比 Bash 更加先进,具有更强的自动补全和插件支持。
- Csh(C Shell):语法与 C 语言相似,主要在一些老旧系统中使用。
- Fish Shell:现代化的 shell,强调用户友好性,自动补全和颜色高亮功能突出。
4.1.3 shell脚本的运行
- Shell 脚本是一种包含多个 shell 命令的文件,通过执行脚本来批量执行任务。
- 脚本文件通常以
.sh
或.bash
后缀命名,可以通过sh
或bash
命令来运行,或者在文件顶部指定解释器并赋予执行权限来直接运行。【还可以 shell解析器 < 脚本.sh 但是这种不可以带参数】
4.2 shell基础
4.2.1 通配符
*
:匹配任意多个字符(包括零个字符)。?
:匹配单个字符。[]
:匹配指定范围内的字符。[^...]
:正则表达式,排除括号内的字符- 如果你是用在
grep
、sed
、awk
里,应该使用[^...]
;
- 如果你是用在
[!... ]
:Shell 文件匹配(通配符),排除括号内的字符- 如果是用于 Shell 文件匹配
,应该使用
[!... ]
。比如 ls 【!a-z】*
- 如果是用于 Shell 文件匹配
,应该使用
{}
:用于列举多个选择项(匹配一项或多项)。
4.2.2 引号
- 单引号
'
:用于将字符串中的所有字符按字面意思处理(即不进行变量替换或命令替换)。 - 双引号
"
:允许变量替换和命令替换。 - 反引号 `【命令】`:用于命令替换,表示执行命令并将输出作为结果插入。
- 注意: 反引号有时候容易与其他符号混淆,尤其在嵌套命令时,建议使用
$(命令)
语法,它更加清晰易懂。
4.2.3 输入/输出重定向符
>
:将标准输出重定向到文件,若文件已存在则覆盖文件内容。>>
:将标准输出追加到文件末尾,若文件不存在则创建该文件。<
:将文件内容作为命令的输入。- 就和直接用文件名没有区别
2>
:将标准错误重定向到文件,若文件已存在则覆盖文件内容。2>>
:将标准错误追加到文件末尾,若文件不存在则创建该文件。&>
:将标准输出和标准错误都重定向到同一个文件,若文件已存在则覆盖文件内容。【2>&1
:将标准错误重定向到标准输出,即将标准错误与标准输出合并。效果一样】&>>
:将标准输出和标准错误都重定向到同一个文件,若文件不存在则创建该文件,且追加到文件末尾。|
(管道符):将前一个命令的标准输出作为下一个命令的输入(纯文本的形式,输出不显示)。tee
:将标准输出同时写入文件并显示在屏幕上。<<
(Here Document):将多行内容提供给命令作为输入,通常用于脚本中。-
命令 << 结束标志 行1 行2 ... 结束标志
-
不一定要EOF,这个部分是结束标志,可以A,B还可以是【你好】,反正由你自己设置。
-
<<<
(Here String):将一个字符串作为输入传递给命令。
4.2.4 命令执行操作符
&
:将命令放入后台执行,命令后加&
即可。sleep 5 &
会在后台暂停 5 秒钟,而echo
会立即执行并输出。
;
:用;
将多个命令连接起来。无论前一个命令是否成功,都会按顺序执行后续命令。&&
:命令链式执行,前一个命令成功后才执行后一个命令。就是编程中的and,物理中的并联,语文中的 只有……才……||
:前一个命令失败时才执行后一个命令。- $?:echo $?将输出上一次结果的正确性,返回为0为正确,其它为错误
4.2.5 小括号和大括号
- 小括号
()
:用于子 shell 执行,可以在括号内运行一组命令,且不影响当前 shell 环境。 - 大括号
{}
:用于命令分组,但不创建子 shell,命令之间需要用分号或换行隔开(左边要有空格,右边要有分号有没有空格无所谓)。
4.2.6 管道符、后台命令符和注释符
- 管道符
|
:将前一个命令的输出作为后一个命令的输入。-
echo "Hello, World!" 会输出字符串 Hello, World!。 | 将 echo 的输出传递给 tr 命令。 tr 'a-z' 'A-Z' 将小写字母转换为大写字母,最终输出 HELLO, WORLD!。
- 后台命令符
&
:将命令放入后台执行。-
sleep 10 & echo "The sleep command is running in the background." 解释: sleep 10 & 会让 sleep 命令在后台运行 10 秒,而不会阻塞当前 shell。 echo "The sleep command is running in the background." 会立即在前台输出。
-
- 注释符
#
:用于在脚本中写注释,后面的内容会被忽略。
4.3 shell编程
4.3.1 变量
Shell 变量 用于存储信息(如文本、数字等)。Shell 中的变量分为环境变量(例如 $PATH
)和用户自定义变量。
-
定义变量:在 Shell 中,变量的定义非常简单,不需要特殊的关键字。
- 变量赋值时不能有空格,等号两边不加空格。
- 引用变量:在使用变量时,需要加上
$
符号来引用。 - 变量类型:
-
本地变量(普通变量) 仅在当前 Shell 会话或脚本中有效。 使用 变量名=值 赋值,不要有空格。 环境变量 使用 export 命令将变量提升为环境变量,使其在 子进程(子 Shell) 中可用。 只读变量 使用 readonly 让变量不可修改。 特殊变量 $? 获取上一个命令的返回状态(0 为成功,非 0 失败) $$ 当前进程的 PID $! 最近一个后台进程的 PID $0 当前脚本名称 $@ 传递给脚本的所有参数(独立) $* 传递给脚本的所有参数(整体) 位置参数变量 用于在 脚本或函数 中接收传递的参数。 $1、$2... $n 代表第 1、2、n 个参数。 $@ 和 $* 代表所有参数。 $# 表示参数个数。 数组变量(书中提到) Shell 支持一维数组,索引从 0 开始。 用 () 定义数组,${数组名[索引]} 访问元素,${数组名[@]} 获取所有元素。 array my_array=(apple banana cherry)空格隔开,引号可以没有 或者 array my_array[0]="apple"…………………… echo "第一个元素:${my_array[0]}" echo "所有元素:${my_array[@]}" 关联数组(仅 Bash 4.0+) 关联数组类似于字典(key-value 形式)。 使用 declare -A 定义。 动态变量(间接引用) var_name="greeting" greeting="Hello, World!" echo "${!var_name}" # 访问 greeting 变量的值
在 Shell 脚本中,变量没有严格的类型,它们默认都是字符串,但可以用于不同的场景,例如整数、数组、环境变量等。
-
- 环境变量 是在操作系统中,用来存储信息的特殊变量。它们对所有程序都可见,甚至对子 shell(从当前 shell 启动的新的 shell)也有效。
-
export name="Alice" # 设置环境变量 # 启动一个新的子 shell bash # 在子 shell 中访问环境变量 echo $name # 输出 "Alice"
-
4.3.2 数值运算
Shell 提供了几种方式来进行数值运算,包括 整数运算 和 浮动点运算。
-
整数运算:
- 使用
(( ))
进行算术运算:(( ))
是 Bash 提供的一种用于进行算术运算的方式,可以进行加、减、乘、除、求余等基本运算。它支持整数运算。没有格式要求。-
a=10;b=5 # 加法 result=$((a + b)) echo $result # 输出 15 # 减法 result=$((a - b)) echo $result # 输出 5 # 乘法 result=$((a * b)) echo $result # 输出 50 # 除法 result=$((a / b)) echo $result # 输出 2 # 求余 result=$((a % b)) echo $result # 输出 0
- 在
(( ))
中,运算符两边不需要$
符号来引用变量,直接使用变量名即可。但是要注意的是,在使用(())为一个变量赋值的时候要用$来引用。
-
- 使用
expr
进行算术运算:expr
是一个外部命令,用于在 Shell 中进行算术运算。它需要在运算符两侧加上空格,运算结果会返回并可以赋值给变量。-
a=10;b=5 # 加法 result=$(expr $a + $b) echo $result # 输出 15 # 减法 result=$(expr $a - $b) echo $result # 输出 5 # 乘法 result=$(expr $a \* $b) # 乘法时 * 需要转义 echo $result # 输出 50 # 除法 result=$(expr $a / $b) echo $result # 输出 2 # 求余 result=$(expr $a % $b) echo $result # 输出 0
- 使用
expr
时,运算符前后需要加空格。 - 乘法 (
*
) 需要使用转义符\
,因为*
在 shell 中是一个通配符。
-
- 使用
let
进行运算:let
是另一个用于进行算术运算的 Bash 内建命令。它的使用方法类似于(( ))
,不过在let
中,变量前不需要$
符号。-
a=10;b=5 # 加法 let result=a+b echo $result # 输出 15 # 减法 let result=a-b echo $result # 输出 5 # 乘法 let result=a*b echo $result # 输出 50 # 除法 let result=a/b echo $result # 输出 2 # 求余 let result=a%b echo $result # 输出 0
- 在
let
命令中,直接使用变量名而不需要$
符号。 let
是 Bash 内建的命令,效率较高,但不支持浮动点数运算。
- 使用
- 浮动点运算: Shell 默认不支持浮动点数的直接运算,可以使用
bc
(Basic Calculator)来执行浮动点数运算。- Shell 默认不支持浮动点数运算,因为
(( ))
、expr
和let
只支持整数计算。如果需要进行 浮动点运算(小数计算),可以使用bc
(Basic Calculator) 命令。 -
echo "bc的运算部分" | bc 比如: result=$(echo "scale=3; 10 / 3" | bc) echo $result scale=2 表示保留 2 位小数。 / 进行除法运算,默认 bc 计算结果会截取整数部分,除非使用 scale 指定小数位数。 scale这个可以省略(最新版本这个没用了,可以不要),引号也可以不要但是建议给
- Shell 不支持浮点运算,但可以使用
bc
计算浮动点数。 scale=n
设定保留 n 位小数,否则默认返回整数。- 可以用
$(echo "... | bc")
把计算结果赋值给变量。 - 支持加
+
、减-
、乘*
、除/
、指数^
、平方根sqrt()
。
- Shell 默认不支持浮动点数运算,因为
4.3.3 比较与控制结构
数值比较:Shell 使用 [
或 test
命令进行整数比较,常见的数值比较运算符如下:
运算符 | 作用 | 示例 | 案例 |
---|---|---|---|
-eq
| 等于 (== )
| [ 5 -eq 5 ] 结果为真
| ![]() |
-ne
| 不等于 (
!= )
| [ 5 -ne 3 ] 结果为真
| ![]() |
-gt
| 大于 (
> )
| [ 5 -gt 3 ] 结果为真
| ![]() |
-lt
| 小于 (
< )
| [ 3 -lt 5 ] 结果为真
| ![]() |
-ge
| 大于等于 (>= )
| [ 5 -ge 5 ] 结果为真
| ![]() |
-le
| 小于等于 (<= )
| [ 3 -le 5 ]
结果为真
| ![]() |
字符串比较:字符串比较用于判断两个字符串是否相等,是否为空等。
运算符 | 作用 | 示例 | 案例 |
---|---|---|---|
= | 字符串等于 | [ "abc" = "abc" ] 结果为真
| ![]() |
!= | 字符串不等 | [ "abc" != "xyz" ] 结果为真
| ![]() |
> | 按字典顺序大于 | [ "b" \> "a" ] 结果为真
| ![]() |
< | 按字典顺序小于 | [ "a" \< "b" ] 结果为真
| ![]() |
-z
| 字符串长度为 0 | [ -z "" ] 结果为真
| ![]() |
-n
| 字符串长度非 0 |
| ![]() |
|
文件比较:文件比较运算符用于检查文件是否存在、是否可读写等。
运算符 | 作用 | 示例 | 案例 |
---|---|---|---|
-e
| 文件存在 | [ -e /etc/passwd ]
| ![]() |
-f
| 是普通文件 | [ -f myfile.txt ]
| ![]() |
-d
| 是目录 | [ -d mydir ]
| ![]() |
-r
| 可读 | [ -r myfile.txt ]
| ![]() |
-w
| 可写 | [ -w myfile.txt ]
| ![]() |
-x
| 可执行 | [ -x script.sh ]
| ![]() |
-s
| 文件非空 | [ -s myfile.txt ]
| ![]() |
-L
| 是符号链接 | [ -L mylink ]
| ![]() |
组合条件:多个条件可以使用 &&
(逻辑与)、||
(逻辑或)和 !
(逻辑非)组合:
组合 | 作用 | 示例 | 案例 |
---|---|---|---|
条件1 && 条件2
| 两个条件都为真 | [ -f file.txt ] && [ -r file.txt ]
| ![]() |
`条件1 | 条件2` | ![]() | |
! 条件
| 取反 | [ ! -e file.txt ]
| ![]() |
Shell 编程中有几种常用的 控制结构,用于控制程序的流程。这个时候我们就开始将shell合在一起吧,写成一个文件。注意第一句最好有#!【shell解析器路径】表示用这个shell解析,不写默认用当前shell
-
if 条件语句:
if
语句用于条件判断,执行符合条件的代码块。if [ 条件 ]; then 命令 elif [ 另一条件 ]; then 命令 else 命令 fi
-
case 语句:
case
语句用于多分支选择,适用于多种情况的匹配。-
case 变量 in 模式1) 命令 ;; 模式2) 命令 ;; *) 默认命令 ;; esac 也可以这样 case 变量 in 模式1) 命令 ;; 模式2) 命令 ;; *) 默认命令 ;; esac
-
-
循环语句:循环结构可以重复执行某些代码块,常见的有
for
、while
和until
。-
for 循环:
for
语句用于遍历列表或范围。-
for 变量 in 值1 值2 值3; do 命令 done ------------------------- for ((初始值; 条件; 递增方式)); do 命令 done -------------------------
-
-
while 循环:
-
while [ 条件 ]; do 命令 done
-
-
until 循环:
until
语句与while
语句相反,当条件为假时执行循环。-
until [ 条件 ]; do 命令 done
-
-
4.4 shell函数
4.4.1 函数定义
Shell 中的函数可以将一组命令打包并通过函数名调用,从而提高代码复用性。
-
定义函数:
-
函数名() { 命令 } 或使用 function 关键字: function 函数名 { 命令 } 比如———————————————— #!/bin/bash hello() { echo "Hello, Shell!" } hello # 调用函数
-
4.4.2 函数参数
函数接收外部传入的参数,可以通过 $1
、$2
等来访问。对于函数中的多个参数,可以使用 $@
或 $*
。
-
访问参数:
-
my_function() { echo "第一个参数:$1" echo "第二个参数:$2" } my_function "Hello" "World"
-
-
打印所有参数:
$@
:表示所有参数,每个参数独立$*
:表示所有参数,作为一个整体$#
:参数个数-
print_params() { echo "所有参数 (\$@):$@" echo "所有参数 (\$*):$*" echo "参数个数:$#" } print_params A B C D
-
遍历所有参数
-
print_each_param() { for arg in "$@"; do echo "参数:$arg" done } print_each_param Apple Banana Cherry
-
-
返回值:
Shell 函数返回值只能是整数(0-255),使用
return
关键字:-
sum() { return $(( $1 + $2 )) } sum 3 5 echo "返回值:$?" # $? 获取函数返回值
-
总结
关键字 | 作用 |
---|---|
$1, $2...
| 访问函数的参数 |
$@ | 以独立字符串形式访问所有参数 |
$* | 以整体字符串形式访问所有参数 |
$# | 计算参数个数 |
$? | 获取函数的返回值 |
return
| 返回整数值 (0-255) |
echo
| 返回字符串或大整数 |
4.5 shell脚本实例
练习题
第二篇 管 理 篇
第5章 用户管理
5.1 用户与用户组管理
5.1.1 用户和用户组
-
用户:Linux系统中的用户是指可以登录和执行任务的身份。每个用户有一个唯一的UID(用户ID)uid=0(root)uid=1-499(系统用户,一般是系统服务所需,所以一般不会创建家目录)剩下的都是普通用户(默认/bin/bash,默认/home/下)。
-
用户组 :用户组是一组用户的集合,便于管理和分配权限。每个用户可以是一个或多个组的成员。
5.1.2 用户和用户组管理
-
用户管理:包括创建用户、删除用户、修改用户信息等。管理用户有助于控制系统的访问权限。
-
用户组管理:为用户分配组、管理组的权限、修改组信息等。用户组有助于统一管理用户的访问权限。
5.2 用户和用户组管理相关的文件(cat 文件路径查看)
5.2.1 passwd文件(/etc/passwd)
- 存储内容:存储系统中所有用户的基本信息。
- 文件权限:
_rw-r--r--_
。 - 字段说明:用户名:密码:UID:GID:描述性信息:主目录:默认shell
5.2.2 shadow文件(/etc/shadow)
- 存储内容:存储用户密码的加密信息。
- 文件权限
:
rw-------_
。 - 字段说明: 用户名:加密密码(未设密码用!!):最后修改密码的日期:最小密码更改天数:最大密码过期天数:密码过期警告天数:禁用日期:保留字段
5.2.3 group文件(/etc/group)
- 存储内容:存储系统中所有用户组的信息。
- 字段说明:组名:密码:GID:组成员
5.2.4 gshadow文件(/etc/gshadow)
- 存储内容:存储用户组的加密信息以及对组的管理权限。
- 字段说明:组名:加密密码:组管理员:组成员
5.3 用户和用户组管理的命令
命令 | 选项 | 参数 | 作用 | 案例 | 命令简介 |
---|---|---|---|---|---|
useradd (添加用户) | -d
| [目录] | 用于指定新用户的主目录 | useradd -d /home/john john
,指定用户john 的主目录为/home/john
| 创建新用户并指定主目录 |
-m
| 无 | 在创建用户时同时创建用户的主目录 | useradd -m john ,会在
/home/john 目录下创建用户主目录
| 创建用户并自动创建主目录 | |
-g
| [组名] | 指定新用户的初始组 | useradd -g admin john ,将用户john 的初始组设置为admin
| 设置新用户的初始组 | |
-G
| [附加组] | 为新用户指定附加组 | useradd -G group1,group2 john ,将john 加入group1 和group2 两个附加组
| 指定用户的附加组 | |
-s
| [shell路径] | 为新用户指定登录时使用的shell | useradd -s /bin/bash john
,为john 指定使用/bin/bash 作为登录shell
| 设置用户的shell | |
-c
| [描述信息] | 为新用户设置描述信息 | useradd -c "John Doe" john
,设置john 的描述信息为"John Doe"
| 为用户添加描述信息 | |
passwd (修改用户密码) | 无选项 | [用户名] | 用于修改用户的密码。普通用户只能修改自己的密码,root用户可以修改任何用户的密码 | passwd john
,修改
john 的密码
| 修改用户密码 |
-e
| 无 | 强制用户下次登录时更改密码 | passwd -e john ,强制john 在下次登录时更改密码
| 强制用户更改密码 | |
-l
| 无 | 锁定用户账户,禁止用户登录 | passwd -l john
,锁定john 账户,使其无法登录
| 锁定用户账户 | |
-u
| 无 | 解锁被锁定的用户账户 | passwd -u john ,解锁john 账户,使其恢复登录权限
| 解锁用户账户 | |
usermod (修改用户信息) | -d
| [目录] | 修改用户的主目录 | usermod -d /home/johndoe john
,将john 的主目录改为/home/johndoe
| 修改用户主目录 |
-g
| [组名] | 更改用户的初始组 | usermod -g admin john
,将john 的初始组更改为admin
| 修改用户初始组 | |
-G
| [附加组] | 将用户添加到指定的附加组 | usermod -G group1,group2 john ,将
john 添加到group1 和group2 两个附加组
| 修改附加组 | |
-s
| [shell路径] | 更改用户登录时使用的shell | usermod -s /bin/zsh john ,将john 的shell改为/bin/zsh
| 修改用户登录shell | |
-l
| [新用户名] | 更改用户的用户名 | usermod -l newname john
,将john 的用户名更改为newname
| 修改用户名 | |
chage (修改用户密码状态) | -E
| [日期] | 设置用户密码过期日期 | chage -E 2023-12-31 john ,设置john 的密码在2023-12-31 过期
| 设置密码过期日期 |
-M
| [天数] | 设置密码的最大使用天数 | chage -M 30 john ,设置
john 的密码最大使用天数为30天
| 设置密码最大使用天数 | |
-W
| [天数] | 设置密码到期前多少天开始提醒用户更改密码 | chage -W 7 john ,设置john 的密码在过期前7天开始提醒用户更改密码
| 设置密码过期前提醒 | |
-l
| 无 | 查看用户的密码状态 | chage -l john ,查看john 的密码过期状态
| 查看密码状态 | |
userdel (删除用户) | -r
| 无 | 删除用户及其主目录 | userdel -r john ,删除john 用户及其在/home/john 下的主目录
| 删除用户和主目录 |
id (查看用户信息) | 无选项 | [用户名] | 查看用户的UID和GID | id john
,查看john 的UID和GID
| 查看用户UID和GID |
su (切换用户) | 无选项 | [用户名] | 切换到指定的用户 | su john
,切换到john 用户
| 切换到指定用户 |
- | 无 | 切换到指定用户并切换到该用户的环境 | su - john ,切换到
john 用户并使用其环境变量
| 切换并加载用户环境 | |
groupadd (添加用户组) | 无选项 | [组名] | 创建一个新的用户组 | groupadd admin ,创建一个名为admin 的用户组
| 创建新的用户组 |
groupmod (修改用户组) | -n
| [新组名] | 修改用户组的名称 | groupmod -n newgroup oldgroup ,将oldgroup 用户组的名称改为newgroup
| 修改用户组名称 |
groupdel (删除用户组) | 无选项 | [组名] | 删除一个空的用户组 | groupdel admin ,删除名为
admin 的空用户组
| 删除空的用户组 |
gpasswd (修改用户组密码) | 无选项 | [组名] | 设置或修改用户组的密码 | gpasswd admin
,为admin 组设置密码
| 修改组密码 |
-a
| [用户名] | 将用户加入指定的用户组 | gpasswd -a john admin ,将john 添加到admin 组
| 将用户加入组 | |
-d
| [用户名] | 将用户从指定的用户组中移除 | gpasswd -d john admin ,将
john 从admin 组中移除
| 从组中移除用户 |
练习题
第6章 文件管理
6.1 文件系统
6.1.1 文件系统的概念
文件:文件系统中存储数据的一个命名对象,是用户中最小的逻辑存储单元。
文件系统结构:在Linux操作系统中,所有的文件和目录都被组织成从一个根节点“/”开始的倒置的树状结构。文件系统通过路径按名称访问文件。
6.1.2 文件结构和类型
-
文件组成:文件由两部分组成:数据项和文件控制块(inode)。数据项是文件内容,文件控制块存储文件的元信息,如文件大小、文件权限、文件的所有者等。
-
文件类型:在Linux中,文件类型通常分为:
- 普通文件:通常的文件,可以包含文本或二进制数据。
- 目录文件:包含对其他文件或目录的指向。目录文件用于组织文件系统。
- 链接文件:分为硬链接(硬连接到文件数据)和软链接(类似Windows快捷方式,指向文件路径)。
- 设备文件:表示物理设备(如磁盘、终端、打印机等)的文件。设备文件又分为字符设备文件和块设备文件。
-
路径表示:
- 绝对路径:从根目录
/
开始的完整路径。比如/home/user/file.txt
。 - 相对路径:从当前工作目录开始的路径。比如
documents/file.txt
(相对当前目录)。
- 绝对路径:从根目录
6.2 文件与目录操作
6.2.1 文件操作命令
命令 | 说明 | 常见选项 | 示例 |
---|---|---|---|
cat
| 用于连接文件并显示文件内容,可以将多个文件内容合并显示,或输出到另一个文件。 | -n
:给所有行编号,-b :仅对非空行编号
| cat file1 file2 > file3 (将file1和file2连接并输出到file3,若file3存在,内容会被覆盖)
|
more
| 分页显示文件内容,通常用于查看较长文件的内容。 | 无选项 | more file.txt (分页显示file.txt的内容)
|
head
| 显示文件的前若干行内容。默认显示前10行。 | -n k :显示前k行,k 是行数
| head -n 10 file.txt (显示file.txt的前10行)
|
tail
| 显示文件的后若干行内容,可以实时查看文件的新增内容。 | -n k :显示后k行,-f :实时跟踪文件新增内容
| tail -n 10 file.txt (显示file.txt的最后10行) ;tail -f file.log (实时显示file.log新增的内容)
|
touch
| 用于创建一个空文件,或者更新文件的访问时间和修改时间戳。 | 无选项 | touch file.txt (如果file.txt不存在,会创建它;如果存在,则更新其访问时间和修改时间)
|
grep
| 在文件中搜索指定的字符模式(字符串或正则表达式)。 | -n :显示行号,-i :忽略大小写,-v :反转匹配
| grep 'pattern' file.txt (在file.txt中查找pattern)
|
sed
| 用于自动化编辑文件中的内容,支持查找替换等功能。 | -i :直接修改文件,-e :执行多个编辑命令,-n :只显示匹配的行
| sed 's/old/new/' file.txt
(将file.txt中的"old"替换为"new")
|
awk
| 用于文本文件的格式化处理,能够根据指定规则进行文本处理和格式化输出。 | -F :指定字段分隔符,
{print $1} :打印第1个字段
| awk '{print $1}' file.txt (打印file.txt中的每一行的第一个字段)
|
cp
| 用于复制文件或目录。可以使用一些选项进行控制,如保留文件属性或递归复制目录。 | -r :递归复制目录,-p :保留文件属性,-i :提示是否覆盖
| cp file1 file2 (复制file1到file2)
|
rm
| 删除文件或目录,使用时要小心,因为删除操作不可逆。 | -r :递归删除,-f :强制删除,不提示
| rm -r dir (递归删除dir目录及其中的所有内容)
|
mv
| 用于移动或重命名文件/目录。如果目标位置存在相同文件,会根据选项进行覆盖或询问。 | -f :强制覆盖,-i :询问是否覆盖,-v :显示移动过程
| mv oldname newname
(将oldname重命名为newname)
|
sort
| 对文件内容进行排序,默认按字母顺序排序。支持反向排序等功能。 | -r :反向排序,-n :按数字大小排序,-k :指定排序的列
| sort file.txt (按字母顺序对file.txt进行排序)
|
wc
| 统计文件中的行数、单词数或字符数。 | -l :统计行数,-w :统计单词数,-m :统计字符数
| wc -l file.txt
|
6.2.2 目录操作命令
命令 | 说明 | 常见选项 | 示例 |
---|---|---|---|
mkdir
| 创建一个新的目录。如果指定的目录不存在,使用-p 选项可以递归创建所有必要的父目录。
| -p :递归创建父目录,-m:手动创建目录权限;
| mkdir -p /tmp/newdir (递归创建目录/tmp/newdir)mkdir -m 711 test
|
rmdir
| 删除空目录,仅适用于删除没有任何文件和子目录的空目录。 | -p :递归删除,从子到父
| rmdir -p /tmp/olddir (删除空目录/tmp/olddir)
|
cd
| 切换当前工作目录。可以使用绝对路径或相对路径切换目录。 | 无选项 | cd /home/user
(切换到/home/user目录),cd ~ (切换到用户的主目录,如果后面有用户名就是到指定用户家目录),(.表示当前目录,~表示当前登录用户家目录,-表示上一次的目录,..上级目录,/根目录)
|
pwd
| 显示当前所在的目录的完整路径。 | 无选项 | pwd (显示当前所在的目录路径)
|
ls
| 列出当前目录或指定目录的内容。可以显示文件、目录的名称。 | -a :显示所有文件,包括隐藏文件,
-l :列出详细信息
| ls -a (显示包括隐藏文件的所有文件),ls -l (显示详细文件列表)
|
ln
| 创建硬链接或软链接(符号链接)。硬链接和软链接的区别是:硬链接共享相同的inode,而软链接是指向原文件的路径。 | -s :创建软链接(符号链接)
| ln -s file1 link1 (创建一个指向file1的软链接link1)
|
比如:-rwxr-xr-x 1 user group 4096 Feb 25 12:34 file.txt
解析 ll 输出格式:
文件类型和权限(-rwxr-xr-x):
第一个字符:表示文件类型。
-:普通文件。
d:目录文件。
l:符号链接(软链接)。
b:块设备文件(比如硬盘)。
c:字符设备文件(比如终端设备)。
p:命名管道(FIFO 文件)。
s:套接字文件。
后面的九个字符:表示文件的权限,分为三组:
第一组(三个字符)是文件所有者的权限(rwx)。
第二组(三个字符)是文件所属组的权限(r-x)。
第三组(三个字符)是其他用户的权限(r-x)。
r 表示可读4,w 表示可写2,x 表示可执行1,- 表示没有该权限0。
硬链接数(1):
这是文件的硬链接数。对于普通文件,通常为 1(自己)。对于目录,它会显示该目录中的子目录的数量(包括 . 和 ..)。
文件所有者(user):
显示文件的所有者(即拥有此文件的用户)。
文件所属组(group):
显示文件所属的用户组。文件可以属于一个组,这个组内的其他用户也可以对文件有权限。
文件大小(4096):
显示文件的大小,单位通常为字节。对于目录,通常显示的是目录的块数,而不是实际的文件大小。
最后修改时间(Feb 25 12:34):
显示文件或目录的最后修改时间。格式通常是“月日 时:分”。如果文件的修改时间超过六个月,则显示年份。
文件名(file.txt):
文件或目录的名称。对于符号链接,还会显示该链接指向的目标文件(例如 link -> target)。
6.3 访问权限管理
6.3.1 权限管理的重要性
文件的权限控制是Linux安全性的重要组成部分。通过适当的权限管理,只有授权的用户和进程才能访问或修改文件。权限可以限制用户对文件的读取、写入和执行操作。
6.3.2 权限位
Linux文件的权限包括三个部分:
- 所有者权限:文件的拥有者可以读、写或执行文件。
- 组权限:文件所属组的用户可以读、写或执行文件。
- 其他人权限:其他用户可以读、写或执行文件。
每种权限使用3个字符表示,如 rwx
(读、写、执行权限)。文件的权限位总共有10个字符,第一位表示文件类型,接下来的9位分成三组,分别表示所有者、组、其他人对文件的权限。
文件权限的数字表示
Linux 使用数字来表示权限,常见的映射关系如下:
- r = 4
- w = 2
- x = 1
- - = 0
每个权限组的三个字符对应的数字权限相加:
rwx
= 4 + 2 + 1 = 7r-x
= 4 + 0 + 1 = 5r--
= 4 + 0 + 0 = 4
因此,rwxr-xr-x
的数字表示就是 755。
6.3.3 修改权限位的命令
umask 是用来设置新文件和目录默认权限的掩码,它表示从默认权限中去除哪些权限。
默认权限:
文件:666(rw-rw-rw-)
目录:777(rwxrwxrwx)
umask 计算方法:
通过将 umask 从默认权限中减去,得到实际权限。
umask 022:文件权限 644(rw-r--r--),目录权限 755(rwxr-xr-x)。
在 umask 0022 中,第一个 0 代表的是特殊权限(SetUID、SetGID 和 Sticky Bit)的掩码,通常用于控制文件和目录的特殊权限设置。
0:没有设置特殊权限。
2:表示 SetUID 和 SetGID 权限掩码(这两个权限通常用于可执行文件)。
1:表示 Sticky Bit(通常用于目录,确保只有文件的所有者才能删除该文件)。
命令 | 选项 | 说明 | 示例 |
---|---|---|---|
chmod | 【三位数字】 | r4w2x1(相加构成) | chmod 755 file.txt 设置文件为所有者可读、写、执行,组和其他人可读、执行。(覆盖)
|
augo(+-=)rwx | 为文件或目录改权限,为(a所有,u所有者,g所有组,o其他用户)修改(+加-减=覆盖)权限 | chmod +x file.txt 为文件添加执行权限。
| |
umask | 022 | 设置文件和目录的默认权限掩码 | umask 022 设置默认文件权限为 rw-r--r-- ,目录为 rwxr-xr-x
|
什么都没有查看设置的权限掩码 | umask
| ||
chown | user | 更改文件或目录的所有者 | chown user file.txt 将文件的所有者更改为
user 。
|
user:group | 同时更改文件或目录的所有者和所属组 | chown user:group file.txt 将文件所有者改为 user ,所属组改为 group 。
| |
-R | 递归更改目录及其内容的所有者 | chown -R user:group /path/to/dir
递归更改目录 /path/to/dir 及其中所有文件的所有者和所属组。
| |
--reference=FILE | 使用另一个文件的所有者和所属组进行更改 | chown --reference=otherfile file.txt 将 file.txt 的所有者和所属组改为 otherfile 的所有者和所属组。
| |
chgrp | group | 更改文件或目录的所属组 | chgrp group1 file.txt 将文件的所属组更改为 group1 。
|
-R | 递归更改目录及其内容的所属组 | chgrp -R group /path/to/dir 递归更改目录 /path/to/dir 及其中所有文件的所属组。
|
练习题
第7章 进程管理
7.1 Linux进程简介
在Linux系统中,进程是正在运行的程序的实例。每个进程都由操作系统管理,系统为每个进程分配资源,并控制它们的执行。
- 进程的概念:每个进程都有一个唯一的标识符——PID(Process ID),同时,它还可能属于某个进程组,有一个父进程(PPID),并且可能会拥有自己的子进程。
- 进程的状态:
- 运行中(Running):进程正在执行。
- 就绪(Ready):进程等待 CPU 分配时间。
- 阻塞(Blocked):进程等待某些事件发生,例如 I/O 操作完成。
- 停止(Stopped):进程已经停止执行,但并未被销毁。
- 僵尸(Zombie):进程已经结束,但其父进程未读取其退出状态。
7.2 进程监控
命令 | 选项 | 说明 | 示例 |
---|---|---|---|
ps
| -a
| 显示所有用户的进程(除去与当前终端相关的进程)。 | ps -a
|
-u
| 显示指定用户的进程。 | ps -u username
| |
-x
| 显示没有控制终端的进程(后台进程等)。 | ps -x
| |
-f
| 显示完整格式的信息,通常包括父进程 PID (PPID)、UID 等。 | ps -ef
| |
-e
| 显示系统中所有进程。 | ps -e
| |
-p
| 显示指定 PID 的进程。 | ps -p 1234
| |
-o
| 自定义显示格式。 | ps -eo pid,comm
| |
pstree(-n,pid排默认)
| -p
| 显示每个进程的 PID。 | pstree -p
|
-u
| 显示进程所属的用户。 | pstree -u
| |
-c
| 显示进程的命令行参数。 | pstree -c
| |
-A
| 使用 ASCII 树显示。 | pstree -A
| |
top
| -u
| 按用户筛选显示进程。 | top -u username
|
-d
| 设置刷新间隔,单位为秒。 | top -d 2
| |
-n
| 设置显示的次数。 | top -n 5
| |
-p
| 按 PID 筛选显示进程。 | top -p 1234
| |
lsof
| -i
| 查看网络连接使用的进程。 | lsof -i
|
-p
| 查看指定进程打开的文件。 | lsof -p 1234
| |
-t
| 只显示进程的 PID。 | lsof -t -i
| |
-u
| 查看指定用户打开的文件。 | lsof -u username
|
ps
命令显示的字段会因使用的选项和参数不同而有所不同。以下是 ps
命令常见字段名及其含义:
字段名 | 说明 |
---|---|
PID | 进程 ID(Process ID),进程的唯一标识符。 |
TTY | 终端类型(Terminal),显示进程关联的终端。若为 ? ,表示该进程无终端。
|
TIME | 进程使用的 CPU 时间。 |
CMD | 启动进程时执行的命令。 |
USER | 进程所属的用户名(或者 UID)。 |
UID | 进程所属的用户的 ID。 |
PPID | 父进程的 PID(Parent Process ID)。 |
STIME | 进程启动时间(Start Time)。 |
VSZ | 进程使用的虚拟内存大小(单位:KB)。 |
RSS | 进程占用的物理内存大小(单位:KB)。 |
STAT | 进程的状态信息。常见的状态有: |
R - 运行状态,
S - 睡眠状态,Z - 僵尸状态,T - 停止状态,D - 不可中断的睡眠等。
| |
%CPU | 进程使用的 CPU 百分比。 |
%MEM | 进程使用的内存百分比。 |
START | 进程开始运行的时间。 |
ELAPSED | 进程已经运行的时间。 |
PGID | 进程组 ID,表示进程所属的进程组。 |
SID | 会话 ID,表示进程所属的会话。 |
这些字段通常可以通过 ps
命令的 -o
选项来自定义,来显示不同的字段。
7.3 结束进程
有时我们需要结束一个不再需要或没有响应的进程。可以通过以下几种方法来终止进程:
-
kill命令:用于发送信号来终止进程。
kill PID
:发送 SIGTERM 信号,优雅地终止进程。kill -9 PID
:发送 SIGKILL 信号,强制终止进程。
-
killall命令:根据进程名称终止进程。
killall process_name
:终止所有名为process_name
的进程。killall -9 process_name
:强制终止所有名为process_name
的进程。
-
pkill命令:根据名称、用户名、进程组等条件发送信号终止进程。
pkill process_name
:发送 SIGTERM 信号终止进程。pkill -9 process_name
:强制终止进程。
-
xkill命令:通过图形界面选择要杀死的进程,点击窗口来结束该进程。
常用信号的表格:
信号 | 数字 | 描述 | 使用示例 |
---|---|---|---|
SIGTERM | 15 | 请求进程优雅退出 | kill 1234
|
SIGKILL | 9 | 强制终止进程 | kill -9 1234
|
SIGINT | 2 | 从终端中断进程(如Ctrl + C) | kill -2 1234
|
SIGHUP | 1 | 终端断开连接或重载配置 | kill -1 1234
|
SIGSTOP | 19 | 暂停进程 | kill -STOP 1234
|
SIGCONT | 18 | 恢复暂停的进程 | kill -CONT 1234
|
SIGQUIT | 3 | 进程退出并生成核心转储 | kill -3 1234
|
SIGUSR1 | 10 | 用户定义信号1 | kill -10 1234
|
SIGUSR2 | 12 | 用户定义信号2 | kill -12 1234
|
SIGALRM | 14 | 定时器信号,通常用于定时任务 | kill -14 1234
|
SIGSEGV | 11 | 段错误(访问非法内存) | kill -11 1234
|
7.4 进程优先级
在Linux中,进程优先级决定了CPU分配给进程的时间片。Linux通过优先级来管理多个进程的执行顺序,较高优先级的进程会更频繁地获得CPU时间。
-
nice命令:启动进程时设置其优先级。
nice -n 10 command
:启动一个进程并设置nice值为10(较低的优先级)。nice -n -10 command
:启动一个进程并设置nice值为-10(较高的优先级)。
-
renice命令:改变正在运行的进程的优先级。
renice -n 10 -p PID
:将指定PID进程的优先级设置为10。renice -n -5 -u username
:为某个用户的所有进程设置新的nice值。
-
优先级范围:
- nice值的范围是-20(最高优先级)到19(最低优先级)。
- 优先级越高,进程越有可能获得CPU时间,反之则会等待更长时间。
-
优先级与实时进程:
- 实时进程优先级为0到99,具有更高的优先级,不受nice值的影响。
- 可以使用
chrt
命令来设置实时进程优先级。
总结:
- 进程监控:通过命令如
ps
、top
、htop
等,管理员可以查看系统进程的状态、资源消耗等。 - 结束进程:通过
kill
、killall
、pkill
等命令,可以终止不需要的或无法响应的进程。 - 进程优先级
:通过
nice
和renice
命令来调整进程的优先级,控制进程的CPU分配。
练习题
第8章 存储管理
8.1 存储设备的查看
在Linux系统中,存储设备主要包括机械硬盘(HDD)、固态硬盘(SSD)、移动存储设备(U盘、SD卡)、RAID磁盘阵列等。为了管理这些设备,需要查看其物理结构、识别设备信息,并进行挂载以供使用。
8.1.1 硬盘结构与分类
1. 机械硬盘(HDD)结构
机械硬盘(HDD,Hard Disk Drive)由多个物理部件组成:
- 盘片(Platter):硬盘的数据存储介质,表面覆盖磁性材料,数据通过磁头读写。
- 磁头(Read/Write Head):用于读取和写入数据,依靠机械臂移动定位到正确的磁道。
- 主轴(Spindle):驱动盘片旋转,使磁头可以访问不同的存储位置。
- 柱面(Cylinder):同一磁盘上所有盘片的同一位置的磁道集合。
- 扇区(Sector):磁盘的最小存储单位,传统扇区大小为 512B,新型高级格式磁盘支持 4KB 扇区(512e/4Kn)。
2. 固态硬盘(SSD)结构
SSD(Solid State Drive)使用 NAND 闪存芯片存储数据,没有机械部件,因此速度更快、抗震性更好。主要组件包括:
- NAND 闪存(Flash Memory) :用于存储数据的非易失性存储芯片。
- 主控芯片(Controller):管理数据的读写、纠错、均衡磨损等。
- 缓存(Cache):用于提升性能,临时存储数据。
3. 硬盘接口类型
不同类型的存储设备采用不同的接口:
- SATA(Serial ATA):常见于HDD和部分SSD,最高支持6Gbps(SATA3)。
- NVMe(Non-Volatile Memory Express):主要用于高速SSD,基于PCIe总线,提供更高的吞吐量(PCIe 3.0/4.0/5.0)。
- SAS(Serial Attached SCSI) :企业级存储设备,支持更高可靠性和速度。
- USB:移动存储设备常见接口,包括USB 2.0、3.0、3.1等。
- SCSI(Small Computer System Interface)是一种广泛用于服务器和存储设备的接口标准,适用于硬盘、光驱、磁带机等设备。
8.1.2 硬盘识别
1 MBR 结构
-
总大小:512字节
-
组成部分:
-
Boot Loader:前 446 字节,用于引导加载程序。
-
Partition Table:接下来的 64 字节(16x4 字节),存储分区信息。
-
结束标志:最后 2 字节,表示分区的结束。
-
2 分区表信息
-
存储内容:分区号(partition ID)、分区的起始柱面和柱面数量。
-
常见分区号:
-
0x5 或 0xf:可扩展分区(extended partition)
-
0x82:Linux 交换区(swap partition)
-
0x83:普通 Linux 分区(Linux partition)
-
0x8e:Linux 逻辑卷管理分区(Linux LVM partition)
-
0xfd:Linux 的 RAID 分区(Linux RAID auto partition)
-
3 分区数量限制
-
MBR 分区表限制:64 字节,每个分区表 16 字节,最多 4 个主分区。
-
扩展分区:通过划分一个可扩展分区,可以增加额外的分区。
-
Linux 内核限制:
-
IDE 硬盘:最多 63 个分区
-
SCSI 硬盘:最多 15 个分区
-
4 硬盘分区的理由
-
方便管理和控制:
-
将数据按应用分类存放在不同分区,简化管理和维护。
-
-
提高系统效率 :
-
缩短磁头移动距离,减少搜寻时间,改善碎片问题。
-
-
磁盘配额功能:
-
限制用户使用的磁盘量,防止浪费。
-
-
便于备份和恢复 :
-
只备份和恢复所需分区,减少数据量,简化操作。
-
通过这些分区策略,可以更有效地管理和使用硬盘资源,提高系统的效率和可靠性。
8.1.3 存储设备的挂载
# 查看可用存储设备
lsblk -f
lsblk # 列出所有块设备(包括分区、挂载信息)
-f # 显示文件系统类型
fdisk -l
fdisk # 磁盘分区工具
-l # 列出所有磁盘及其分区信息
# 创建挂载目录
mkdir /mnt/mydisk
# 挂载本地磁盘
mount -t ext4 /dev/sdb1 /mnt/mydisk
mount # 挂载设备
-t ext4 # 指定文件系统类型(如 ext4、xfs、vfat、ntfs 等)
/dev/sdb1 # 要挂载的设备
/mnt/mydisk # 挂载到的目标目录
# 如果文件系统不确定,可自动检测:
mount /dev/sdb1 /mnt/mydisk(也就是不指定)
【
挂载 NTFS 格式(Windows 磁盘)
mount -t ntfs-3g /dev/sdb1 /mnt/mydisk
ntfs-3g # 使用 NTFS-3G 驱动(适用于 NTFS 文件系统)
如果 ntfs-3g 未安装,可使用以下命令安装:
sudo apt install ntfs-3g # Debian/Ubuntu
sudo yum install ntfs-3g # CentOS/RHEL
挂载 U 盘(FAT32 / exFAT)
mount -t vfat /dev/sdb1 /mnt/mydisk
-t vfat # 挂载 FAT32 格式 U 盘
-t exfat # 挂载 exFAT 格式 U 盘(需安装 exfat-utils)
如果 exfat-utils 未安装,可使用:
sudo apt install exfat-utils exfat-fuse # Debian/Ubuntu
sudo yum install exfat-utils exfat-fuse # CentOS/RHEL
挂载 ISO 文件
mount -o loop myimage.iso /mnt/iso
-o loop # 使用回环设备挂载 ISO 文件
myimage.iso # ISO 文件路径
/mnt/iso # 挂载目录
挂载网络共享(NFS)
mount -t nfs 192.168.1.100:/shared_folder /mnt/nfs
-t nfs # 指定 NFS 类型
192.168.1.100:/shared_folder # 远程 NFS 共享地址
/mnt/nfs # 本地挂载点
如果未安装 NFS 客户端,可安装:
sudo apt install nfs-common # Debian/Ubuntu
sudo yum install nfs-utils # CentOS/RHEL
挂载 Windows 共享(CIFS/SMB)
mount -t cifs -o username=user,password=pass //192.168.1.100/shared /mnt/smb
-t cifs # 指定 CIFS(Windows 共享)
-o username=user,password=pass # 访问共享所需的用户名和密码
//192.168.1.100/shared # 远程共享路径
/mnt/smb # 本地挂载点
安装 CIFS 支持(如果未安装):
sudo apt install cifs-utils # Debian/Ubuntu
sudo yum install cifs-utils # CentOS/RHEL
】
# 取消挂载
umount /mnt/mydisk
umount # 卸载挂载的设备
/mnt/mydisk # 挂载点路径
# 如果设备繁忙,强制卸载:
umount -l /mnt/mydisk # 立即卸载但可能有未完成的读写
umount -f /mnt/mydisk # 强制卸载
# 开机自动挂载(修改 /etc/fstab)
编辑/etc/fstab
添加这样的内容——》/dev/设备名(或者uuid) /挂载路径 文件系统(比如ext4) default 0 2
文件系统(ext4、xfs、vfat、ntfs-3g、nfs、cifs)
defaults # 默认挂载选项(可读写、自动挂载等rw,noatime)
0 # 是否需要 dump 备份(一般设为 0,不备份)
2 # fsck 自检顺序(1 为 root 分区,其他设为 2,0不检查)
使用blkid可以查看设备的uuid,建议使用uuid
mount -a 【-v 输出详细过程】命令用于挂载 /etc/fstab 中所有未挂载的条目(建议)
source /etc/fstab
8.2 分区管理
8.2.1 fdisk命令
fdisk
是一个用于管理磁盘分区的命令行工具,常用于创建、删除、修改磁盘分区。
fdisk
-l:列出所有磁盘及其分区。
fdisk /dev/设备名
选择磁盘进行分区:
常见操作:
m:显示帮助菜单
p:查看当前分区表
n:创建新分区
d:删除分区
t:修改分区类型
w:保存更改并退出
q:不保存更改并退出
8.2.2 parted命令
8.2.2 partedees (部分)
parted
是另一个分区管理工具,相比 fdisk
更适合处理大容量磁盘和支持多种文件系统类型的分区管理。
8.3 磁盘管理工具
8.3.1 df命令
df
(Disk Free)命令用于显示文件系统的磁盘空间使用情况,包括总空间、已用空间、剩余空间以及文件系统的挂载点。
df -h 【路径:表示只显示指定路径磁盘情况】
-h # 以人类可读的格式(例如 KB、MB)显示磁盘空间
-a:包括所有文件系统(即使它们的空间为零,或是虚拟文件系统)。
-T:显示每个文件系统的类型(如 ext4、xfs、tmpfs 等)。
-H:以 1000 为进制(而不是 1024)显示空间,这与 -h 类似,但是采用更标准的单位,例如 KB = 1000 字节,而不是 1024 字节。
-l:仅列出本地文件系统,忽略网络文件系统(例如 NFS)。
-L:显示实际挂载的文件系统,而不仅仅是占用空间的文件系统。适用于合并多个设备的场景(如 LVM 或 RAID)。
-i:显示 inode 使用情况,而不是磁盘使用情况。inode 是文件系统中用于存储文件的元数据的结构,通常用于显示文件数量和文件系统结构的健康情况。
-P:以 POSIX 标准格式输出,适用于脚本处理。
--total:显示所有文件系统的总计信息。
--sync:将输出文件系统的同步信息,以帮助调试。
-x <类型>:排除指定类型的文件系统。在输出时不显示指定类型的文件系统(例如,不显示 tmpfs 或其他类型的虚拟文件系统)。
--exclude-type=<类型>:与 -x 类似,排除指定类型的文件系统,只是这个选项可以支持多个类型。
--block-size=<size>:自定义输出的磁盘块大小。你可以指定块大小(例如:512、1K、4M)。
文件系统 显示设备或分区的名称(例如 /dev/sda1 或 /dev/mapper/centos-root)
大小 显示文件系统的总容量,以人类可读格式(KB、MB、GB)
已用 显示已使用的磁盘空间大小
可用 显示可用的磁盘空间大小
已用百分比 显示已使用空间的百分比
挂载点 显示文件系统的挂载位置(例如 / 或 /home)
8.3.2 du命令
du
(Disk Usage)命令用于显示指定目录下的磁盘空间使用情况。它可以递归地显示文件或目录的空间使用详情。
du [选项] [文件或目录]
-h:以“人类可读的”格式显示大小(例如 KB、MB、GB)。
-a:列出所有文件的空间使用情况,而不仅仅是目录。
-s:仅显示指定目录的总空间使用情况,不显示子目录的空间使用情况。
-c:显示所有列出目录或文件的总计大小。
-B <block_size>:指定输出时使用的块大小(例如 -B 1M 用 MB 单位显示空间)。
-d <depth>:指定显示目录层级的深度。例如,-d 1 会显示当前目录和直接的子目录的空间使用情况。
--max-depth=<depth>:限制递归目录的深度。例如,--max-depth=2 显示当前目录以及其下的两层子目录的空间使用情况。
--exclude=<pattern>:排除符合指定模式的文件或目录。可以使用通配符。
-L:如果目录中有符号链接,-L 会让 du 跟随符号链接并计算链接目标的空间。
-x:仅显示同一文件系统中的文件和目录,不跨越文件系统。
--time:显示目录的最后修改时间。
8.3.3 fsck命令
fsck
(File System Consistency Check)命令用于检查和修复文件系统的错误。它会扫描文件系统并尝试修复损坏的部分,尤其在磁盘突然掉电后,文件系统可能出现不一致的情况时,可以通过 fsck
修复。
fsck [选项] [设备]
-A:检查 /etc/fstab 文件中列出的所有文件系统。
-a:自动修复文件系统的错误,不需要用户确认。注意:这通常只适用于某些文件系统(如 ext4)。
-y:自动回答“yes”来修复所有发现的错误,而不询问用户。
-n:模拟修复过程,显示所有错误,但不做任何更改(“dry-run”模式)。
-f:强制检查,即使文件系统看起来没有问题,也会进行检查。这通常用于某些文件系统被标记为“干净”时。
-T:在检查过程中不显示每个文件系统的详细信息,仅显示摘要。
-C:显示文件系统检查的进度信息。
-l:列出所有检查的文件系统。
-V:以详细模式显示更多的检查过程信息(用于调试)。
-t <type>:指定文件系统类型。例如,-t ext4 用于检查 ext4 类型的文件系统。
8.4 磁盘阵列
表格来形象化地对比不同的 RAID 级别:
RAID 级别 | 描述 | 性能 | 冗余保护 | 存储效率 | 适用场景 | 比喻 |
---|---|---|---|---|---|---|
RAID 0 | 条带化(数据分割存储到多个硬盘) | 高读写性能 | 无冗余保护 | 100%(所有硬盘容量都用来存储数据) | 高速存储,要求无冗余保护的场景 | 像在多个桌子上拼图,缺少任何一块拼图就不能完成。 |
RAID 1 | 镜像(数据完全复制到多个硬盘) | 性能较低 | 高冗余保护 | 50%(硬盘总容量的一半用于存储数据) | 需要高冗余保护的场景 | 像有两台相同的打印机,打印相同的内容,保证万一一台坏了,另一台还能继续工作。 |
RAID 5 | 分布式奇偶校验(数据和校验信息交替存储) | 性能较高 | 中等冗余保护 | 67%(硬盘总容量的 2/3 用于存储数据) | 存储效率与冗余平衡的场景 | 像有 3 台硬盘,其中两台存储数据,一台存储校验信息,确保一个硬盘坏了不丢数据。 |
RAID 10 | 镜像 + 条带化(结合 RAID 1 和 RAID 0) | 高读写性能 | 高冗余保护 | 50%(硬盘总容量的一半用于存储数据) | 需要高性能和高冗余的场景 | 像有两组打印机,每组 2 台,一台打印,另一台作为冗余,提升效率且保证安全。 |
mdadm --create <设备> --level=<模式> --raid-devices=<磁盘数量> <磁盘设备>
--create <设备>:用于创建一个新的 RAID 阵列,<设备> 指定该 RAID 阵列的设备名称。例如 /dev/md0 表示创建一个名为 /dev/md0 的 RAID 阵列(注意这是mdx的形式,设置其他名字也会被改,建议用什么阵列写什么比如raid5就写/dev/md5)。
--level=<模式>:指定 RAID 阵列的模式。常见的 RAID 级别有:
0:条带化(RAID 0)
1:镜像(RAID 1)
5:分布式奇偶校验(RAID 5)
10:镜像 + 条带化(RAID 1+0 或 RAID 10)
--raid-devices=<磁盘数量>:指定要包含的磁盘数量,例如 2、3、4 等,具体数字取决于 RAID 级别的要求。
<磁盘设备>:列出要加入 RAID 阵列的磁盘设备名称,例如 /dev/sda、/dev/sdb 等。
比如
mdadm --create /dev/md0 --level=0 --raid-devices=2 /dev/sda /dev/sdb
要取消(删除)一个已经创建的 RAID 阵列,可以使用以下步骤,主要通过 mdadm 工具来完成。以下是常见的操作:
停止 RAID 阵列:mdadm --stop /dev/md0
移除 RAID 阵列:mdadm --remove /dev/md0
删除 RAID 配置文件(可选):rm /etc/mdadm/mdadm.conf
清除硬盘上的超级块信息:mdadm --zero-superblock /dev/sda
卸载磁盘分区:umount /dev/sda1
删除磁盘分区:使用 fdisk 或 parted
练习题
第9章 设备管理
设备管理是操作系统的重要组成部分,它涉及到对计算机硬件的访问和管理。Linux 系统通过设备文件来与硬件设备进行交互,设备文件通常位于 /dev
目录下。通过不同的命令,可以获取硬件设备的状态、性能及配置信息。
9.1 设备文件
在 Linux 中,设备文件是表示硬件设备的一种特殊文件。通过设备文件,用户可以与硬件设备进行通信。设备文件通常分为两类:
- 字符设备:直接按字节流与设备通信,如终端、打印机等设备。
- 块设备:按块进行读写的设备,典型的如硬盘、U盘等。
设备文件通常位于 /dev
目录下,每个设备都有一个相应的设备文件,例如 /dev/sda
表示第一个硬盘,/dev/tty1
表示第一个终端。
9.2 常用的设备命令
9.2.1 查看CPU信息的命令
lscpu
: lscpu
命令显示关于 CPU 架构的信息,包括 CPU 的数量、核心数、线程数、架构类型等。
cat /proc/cpuinfo
: 通过查看 /proc/cpuinfo
文件,用户可以获取更详细的 CPU 信息,例如每个核心的详细信息。
top
或 htop
: top
命令可以显示 CPU 使用情况,以及系统中各个进程的实时资源占用情况。htop
是 top
命令的增强版,提供了更友好的图形界面。
9.2.2 查看内存信息的命令
free
: free
命令显示系统内存的使用情况,包括总内存、已用内存、空闲内存、缓存等信息。
free
free -h
输出:
total used free shared buff/cache available
Mem: 16Gi 4.2Gi 9.7Gi 191Mi 2.1Gi 11Gi
Swap: 2.0Gi 0B 2.0Gi
total:总内存
used:已用内存
free:空闲内存
shared:共享内存
buff/cache:用于缓存的内存
available:可以被进程使用的内存
cat /proc/meminfo
: 查看 /proc/meminfo
文件,获取更详细的内存使用信息
vmstat
: vmstat
命令提供了关于虚拟内存、进程、CPU 活动等方面的统计信息。
9.2.3 查看块设备的命令
lsblk
: lsblk
命令列出所有可用的块设备(硬盘、分区等),并显示设备的大小、挂载点等信息
fdisk -l
: fdisk
命令用于显示硬盘的分区表信息。-l
选项列出所有磁盘和分区信息。
blkid
: blkid
命令可以列出所有块设备的详细信息,包括设备的文件系统类型和UUID
9.2.4 磁盘配额的命令
磁盘配额是用来限制用户或组使用磁盘空间的功能。Linux 提供了多个命令来查看和管理磁盘配额。
quota: quota 命令用于显示当前用户或组的磁盘配额和使用情况。
quota -u 用户名
blocks:已使用的磁盘块数。
soft:软限制,表示用户在配额超过软限制时有一段宽限期。
hard:硬限制,表示用户不能超过的最大磁盘使用量。
inodes:已使用的文件数量。
repquota: repquota 命令用于生成报告,显示所有用户和组的磁盘配额使用情况。
repquota <挂载点>
used:用户已使用的磁盘空间。
soft 和 hard:用户的软限制和硬限制。
inodes:用户文件的数量。
edquota: edquota 命令用于编辑用户或组的磁盘配额。
edquota <用户名>
运行该命令后,会打开一个编辑器,显示如下格式的内容,允许管理员设置用户的软限制和硬限制。
Disk quotas for user username (uid 1001):
/dev/sda1:
blocks: 10240 soft: 20480 hard: 40960
inodes: 64 soft: 128 hard: 256
在编辑器中,管理员可以修改 soft 和 hard 的值。
setquota: setquota 命令用于设置用户或组的磁盘配额
setquota -u <用户名> <软限制> <硬限制> <软inode限制> <硬inode限制> <挂载点>
setquota -u username 10000 15000 0 0 /home
-u:表示设置用户的配额。
10000:软限制,单位为块(通常为 1KB)。
15000:硬限制,单位为块(通常为 1KB)。
0:软 inode 限制。
0:硬 inode 限制。
/home:指定配额适用的挂载点。
说明:此命令会为 username 用户设置磁盘配额,软限制为 10,000 块,硬限制为 15,000 块,并且不限制 inode 使用。