进程,系统性能管理监视工具和计划任务

内核,CPU,内存,进程简单介绍。系统性能管理监视工具和计划任务工具。

内核,CPU,内存

内核介绍

内核 是操作系统最基本的部分,功能强大:

  • 系统调用接口
  • 进程管理
  • 内存管理
  • 文件系统管理
  • 设备驱动
  • 硬件抽象

CPU

CPU 分片(时间分片,轮转调度),确保了每个进程或线程都能获得一定的 CPU 时间。

并发,并行

image-20241118091713767

寄存器

  • 地址寄存器(AR),用来保存 CPU 当前所访问的主存单元的地址
  • 指令寄存器(IR),用来保存当前正在执行的一条指令
  • 程序计数器(PC),指出下一条指令在主存储器中的地址
  • 数据寄存器(DR),CPU 和主存、外设之间信息传输的中转站
  • 通用寄存器(x64,e 变 r,加新的通用寄存器:r8-r15
    • eax: 通常用来执行加法,函数调用的返回值一般也放在这里面
    • ebx: 数据存取
    • ecx: 通常用来作为计数器,比如 for 循环
    • edx: 读写 I/O 端口时,edx 用来存放端口号
    • esp: 栈顶指针,指向栈的顶部
    • ebp: 栈底指针,指向栈的底部,通常用 ebp+偏移量 的形式来定位函数存放在栈中的局部变量
    • esi: 字符串操作时,用于存放数据源的地址
    • edi: 字符串操作时,用于存放目的地址的,和 esi 两个经常搭配一起使用,执行字符串的复制等操作
  • 程序状态字寄存器(PSW),用来表征当前运算的状态及程序的工作方式。
  • 段寄存器:段基址+段内偏移段
  • ……

内存

Page Frame(页框)

物理内存管理中的一个基本单位。

物理内存被划分为固定大小的块,这些块称为 页框(Page Frame)。大小 4K,大页框 2MB。

页框的状态通常分为以下几种:

  1. 已分配(Allocated)
    • 页框已分配给某个进程的虚拟页。
  2. 未分配(Free)
    • 页框当前未被使用,可以分配给新的虚拟页。
  3. 脏页框(Dirty Page Frame)
    • 页框中的数据被修改,但尚未写回磁盘。
  4. 共享页框(Shared Page Frame)
    • 页框被多个进程共享(如共享库或 IPC 中的共享内存)。

Page(页)

操作系统通过页表将虚拟内存中的 页(Page) 映射到物理内存中的页框。

脏页(Dirty Page):内存中被修改过但尚未写回到磁盘上的页。减少 IO

Page table(页表)

页表实际上存储在 CPU 的 内存管理单元 (MMU :Memory Management Unit)

内存映射

内存地址转换,其实就是这样三个步骤:

  • 把虚拟内存地址,切分成页号和偏移量;
  • 根据页号,从页表里面,查询对应的物理页号;
  • 直接拿物理页号,加上前面的偏移量,就得到了物理内存地址。
1
2
3
4
| 一级索引 (20 bits) | 页内偏移 (12 bits) |

页表大小:
2^20 * 4bytes = 4MB

内存分页寻址

多级页表

一级页表查找使用哪个二级页表

二级页表查物理页号

1
| 一级索引 (10 bits) | 二级索引 (10 bits) | 页内偏移 (12 bits) |

img

优化多级页表的地址转换:TLB

CPU 的 TLB(Translation Lookaside Buffer)来缓存页表条目:

  1. TLB 命中
    • 如果虚拟地址的页表条目在 TLB 中,直接完成地址转换,无需访问多级页表。
  2. TLB 未命中
    • 如果未命中,需要逐级查找页表获取地址映射,并将结果缓存到 TLB。

页面换入换出(Page Swapping)

当物理内存不足时,操作系统会将不常使用的页面从物理内存换出到磁盘(即页面置换),腾出空间给新页面。这种机制被称为 页面换入换出(Page Swapping)

  • 页表条目中会记录页面是否在磁盘上(有效位为 0)。
  • 如果程序访问一个在磁盘上的页面,会触发 缺页异常(Page Fault),操作系统会将页面换入物理内存并更新页表。

buffer(缓冲),cache(缓存)

缓冲区是一个用于 临时存储数据 的内存区域,其主要目的是协调数据生产者和消费者之间的速率差异,或在设备之间传递数据时作为中转。

缓存区是一个用于 加速数据访问 的高效存储区域,其主要目的是存储热点数据或最近使用的数据,以减少慢速设备或计算的频繁访问。

堆(heap),栈(stack)

  1. 栈(Stack)
    • 一块连续内存区域,用于存储函数调用相关的数据(如局部变量、函数参数、返回地址等)。
    • 栈有一个 ESP 寄存器管理
      • ESP(栈顶指针):指向当前栈顶的位置。
      • EBP(基址指针):指向当前函数栈帧的基址(底部)。通过 EBP,定位栈上的参数。
        • 调用函数过程:
          • EBP 指 Main 函数栈底
          • 压入 func 参数,ESP 指栈顶
          • call func:压入返回地址
          • EBP 指 func 函数栈底
  2. 堆(Heap)
    • 由程序员通过动态内存分配函数(如 mallocnew)显式申请的一块内存区域,大小和生命周期由程序员控制。

image-20241118201645506

代码段(.text): 用来存放可执行文件的操作指令

数据段(.data): 用来存放可执行文件中已初始化全局变量

BSS 段(.bss): Block Started by Symbol”的缩写, 意为“以符号开始的块,BSS 段包含了程序中未初始化的全局变 量,在内存中 bss 段全部置零。

内存问题

内存泄露 Memory Leak

申请了内存,但使用完并未释放申请的内存。

如果一致重复这样的申请,使用的内存会不断增加。

内存溢出:Memory Overflow

数据超出了其存储空间的范围,导致数据损坏或程序崩溃。:整数溢出和缓冲 区溢出

申请了 20M 的空间,但是在这个空间写入 20M 以上字节的数据,就是溢出。

内存不足:OOM

Out Of Memory 内存用完了。

Java 会选一个进程杀死。

内存淘汰策略

内存淘汰策略的核心目标是 在有限的内存资源下最大限度地减少缺页率

先进先出(FIFO)

按照页面进入内存的顺序进行淘汰,最早进入内存的页面最先被替换。

最近最少使用(LRU - Least Recently Used);加权 LRU

按时间

淘汰最近最少使用的页面,假设最近使用过的页面在未来可能仍会被使用。

最不经常使用(LFU - Least Frequently Used)

按访问次数

淘汰访问次数最少的页面,假设访问频率低的页面未来也不太可能被访问。

时钟算法(Clock Algorithm,改进型 FIFO);二级时钟

使用一个环形队列和访问位(Access Bit)。(二级时钟多一个修改位)

每次访问页面时,将其访问位设置为 1;淘汰时跳过访问位为 1 的页面,并将其访问位清零,最终淘汰访问位为 0 的页面。

最优页面淘汰(OPT - Optimal)无法在实际系统中实现

淘汰未来最长时间不会被访问的页面。(无法在实际系统中实现,因为未来的页面访问情况是未知的。)

时间,空间复杂度

image-20241118204654392

进程

概览

进程概念

进程是 系统 进行资源分配与调度的基本单位。

进程是运行中的程序。

进程是程序的一次执行过程,它包含了程序的 代码、数据和运行状态 等信息。

init:第一个进程(PID = 1),从 CentOS7 以后为 systemd

进程分类

  1. 按资源使用划分

    • CPU 密集型
    • IO 密集型
  2. 按运行方式划分

    • 守护进程:daemon,在系统引导中启动的进程
    • 前台进程:前台进程是直接与用户交互的进程

    注意:两者可相互转化

进程结构

每个进程都有自己的资源,由操作系统分配,内存,栈,文件描述符等信息

进程由程序、数据和进程控制块(Program Control Block,PCB)三部分组成。

  • 程序是进程要执行的指令集合,

  • 数据是进程在执行过程中需要处理的信息

  • 进程控制块则包含了进程的各种信息和控制信息,

    • 进程标识符(PID)、
    • 状态、
    • 优先级、
    • 程序计数器、
    • 寄存器集合等。

    image-20241118100901074

线程

一个进程可以包含多个线程,线程是 **CPU ** 调度和执行的基本单位。

线程由线程 ID、当前指令指针(PC)、寄存器和堆栈组成。

线程共享进程资源:

  • 共享代码段、数据段和打开的文件。
  • 每个线程有自己的寄存器和栈,用于维护独立的执行流。

进程与线程

image-20241118101940553

进程拥有独立的内存单元和资源,而线程则共享进程的资源。这使得线程在切换时开销较小,因为不需要 切换整个进程的上下文

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 查看进程的相关信息
ls /proc/PID

# 查看进程中的线程 - 包括进程本身
grep -i threads /proc/PID/status

# 查看进程的二进制文件(软链接)
ll /proc/PID/exe

# 查看进程打开的文件(软链接)
ll /proc/PID/fd/

# 查看进程,带pid
pstree -p

进程结构

核心数据结构:task_struct

task_struct 是 Linux 中用来描述进程的主要结构体。它定义在内核源码的 include/linux/sched.h 文件中,包含以下主要字段:

基本信息

  • pid:进程的唯一标识符(Process ID)。
  • tgid:线程组 ID,在多线程程序中,所有线程共享同一个 tgid
  • comm:进程名称,通常是可执行文件的名称(15 字节长度限制)。

状态信息

  • state

    :表示进程的当前状态,例如:

    • TASK_RUNNING:正在运行或准备运行。
    • TASK_INTERRUPTIBLE:可被信号中断的睡眠状态。
    • TASK_UNINTERRUPTIBLE:不可被信号中断的睡眠状态。
    • TASK_STOPPED:进程已停止。
    • TASK_DEAD:进程已终止。
  • exit_state:当进程退出时记录其状态,如僵尸状态。

父子关系

  • parent:指向父进程的 task_struct
  • children:链表,包含当前进程的所有子进程。
  • sibling:指向同一父进程的兄弟进程。

链表指针

  • tasks:用于将所有进程组织成一个全局的双向循环链表,通过 nextprev 遍历。
  • thread_group:线程组链表,用于管理同一线程组的所有线程。

调度信息

  • prio:进程的优先级。
  • static_prio:静态优先级,用户指定。
  • normal_prio:进程的普通优先级。
  • rt_priority:实时进程的优先级。
  • sched_class:调度类(如 CFS 调度器、实时调度器)。

记账信息

  • start_time:进程创建的时间。
  • utime:用户态运行时间。
  • stime:内核态运行时间。
  • real_start_time:从系统启动到该进程开始运行的时间戳。

内存管理

  • mm:指向 mm_struct 的指针,描述了进程的内存空间信息。
  • active_mm:用于内核线程,共享另一个进程的地址空间。
  • stack:进程的内核栈。

文件和 IO

  • files:指向 files_struct 的指针,描述进程打开的文件描述符表。
  • fs:指向 fs_struct 的指针,包含当前工作目录和根目录的信息。
  • io_context:I/O 调度信息。

信号

  • signal:指向 signal_struct 的指针,包含进程的信号处理信息。
  • blocked:屏蔽的信号集合。
  • pending:挂起的信号集合。

内核线程

  • flags:用于标记进程的特殊状态,例如是否是内核线程。
  • thread:用于存储硬件上下文(如寄存器)信息,特别是在上下文切换时使用。

用户空间和内核空间

内存 中一部分分配给 内核使用,一部分分配给 应用程序使用

分别称之为 内核空间用户空间

image-20241119090008870

  • 用户空间(User Space):
    • 应用程序的内存区域
    • 低地址位
    • API(应用程序接口)
  • 内核空间(Kernel Space):
    • 内核运行的内存区域
    • 高地址位
    • System Call Interface(系统调用接口)

用户态(User Mode)和内核态(Kernel Mode)切换

用户态是应用程序运行的环境,权限受限,不能直接访问硬件资源或内核功能。

内核态是操作系统内核运行的环境,具有最高权限,直接控制硬件和管理系统资源。

  • 系统调用
    • 用户空间进入内核空间的主要途径
  • 中断和异常
    • 中断是由硬件或外部事件触发的机制,内核通过中断处理程序响应这些事件。
    • 异常是由 CPU 执行指令时检测到的错误(Page Fault,Trap:用户态程序故意触发异常进入内核)触发的。
  • 上下文切换
    • 进程切换,线程切换,用户态内核态切换,中断切换,异常切换
    • 发生条件
      • 进程被抢占:时间片到期或更高优先级的任务需要执行。
      • 系统调用或中断:用户态程序主动进入内核态。
      • I/O 等待:进程等待 I/O 完成,需要切换到其他任务。
    • 保存当前状态
      • 操作系统保存当前进程的 CPU 寄存器、程序计数器、栈指针等状态。
    • 切换到新任务
      • 恢复另一个任务的状态,包括寄存器、栈、程序计数器等。
      • CPU 开始执行新任务。

进程状态

  • 新建状态(New)
    • 进程正在创建中,尚未被操作系统调度执行。
      • 操作系统已为进程分配了必要的资源(如 PCB,Process Control Block)。
      • 尚未进入调度队列
  • 就绪状态(Ready)
    • 进程已分配必要资源,等待 CPU 调度运行。
      • 位于 调度队列中,随时可以获得 CPU。
      • 未占用 CPU。
  • 运行状态(Running)
    • 进程正在 CPU 上运行,执行其指令。
      • 只有一个进程(单核系统)可以处于运行状态。
      • 多核系统中,每个 CPU 核心可以运行一个进程。
  • 阻塞状态(Blocked / Waiting)
    • 进程 等待某种事件完成(如 I/O 操作、信号或资源),暂时无法运行。
      • 阻塞进程不在调度队列中。
      • 只有等待的事件完成后才能转入就绪状态。
  • 终止状态(Terminated)
    • 进程已完成执行或被强制结束。
      • 进程的资源被回收。
  • 挂起状态(Suspended)
    • 阻塞 → 挂起
      • 系统内存不足,进程被换出到外存。
    • 挂起 → 阻塞
      • 系统资源恢复,挂起进程重新加载到内存,但仍等待事件。

状态转换

image-20241119144245751

子进程

父子进程

父进程

父进程可以通过系统调用 fork() 创建子进程。

fork() 函数

  • 创建一个几乎完全相同的子进程。
  • 子进程从父进程的当前位置开始执行。
  • 返回值:
    • 父进程中返回子进程的 PID。
    • 子进程中返回 0。
    • 如果创建失败,返回 -1。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid = fork(); // 创建子进程
    if (pid == 0) {
        // 子进程
        printf("This is the child process. PID = %d\n", getpid());
    } else if (pid > 0) {
        // 父进程
        printf("This is the parent process. PID = %d\n", getpid());
    } else {
        // 创建失败
        perror("fork failed");
    }
    return 0;
}

子进程

子进程的生命周期

  1. 创建
    • 父进程调用 fork()
  2. 执行
    • 子进程可以执行父进程代码,也可以通过 exec() 执行新程序。
  3. 退出
    • 子进程完成任务后调用 exit() 终止。
    • 退出状态会保存在内核中,直到被父进程回收。

回收子进程

  • 父进程调用 wait()waitpid() 获取子进程的退出状态,并释放子进程的资源。
    • wait() 函数
      • 阻塞父进程,直到任意一个子进程退出。
      • 返回退出的子进程的 PID。
    • waitpid() 函数

  • 父进程使用 SIGCHLD 信号处理子进程退出
    • 当子进程退出或停止时,操作系统会向父进程发送 SIGCHLD 信号。
    • 父进程可以捕获此信号,并在信号处理程序中处理子进程的退出状态。
方式 特点 适用场景
wait() 阻塞父进程,等待子进程退出。 子进程较少,父进程无需执行其他任务。
waitpid() 支持非阻塞模式和指定等待的子进程,灵活性更高。 父进程需要并行处理其他任务或管理多个子进程。
SIGCHLD 信号 异步通知父进程子进程的退出事件,无需阻塞。 父进程需要实时响应子进程状态,且需管理大量子进程。

僵尸进程

僵尸进程是指 已经终止运行,但其退出状态尚未被父进程回收 的子进程。

杀了,但没有死。

形成原因

  • 当子进程结束后,操作系统会通知父进程,父进程需要调用系统调用(如 wait()waitpid())回收子进程的退出状态。

  • 如果父进程没有回收子进程状态,子进程就会变成僵尸进程。

僵尸进程占用进程表条目(PID)。

孤儿进程

孤儿进程是指 父进程已经终止,但子进程仍在运行 的进程。

孤儿进程会被操作系统的 init 进程(PID 1) 接管,成为其子进程。

形成原因

  • 父进程意外终止或正常结束,但子进程仍在运行。
  • 子进程未完成其任务,继续执行。

进程调度

调度目标

  • 最大化 CPU 利用率:尽量减少 CPU 空闲时间。
  • 最大化吞吐量:单位时间内完成的任务数量。
  • 最小化周转时间:从提交任务到完成所需的总时间。
  • 最小化等待时间:进程在就绪队列中等待的总时间。
  • 最小化响应时间:从请求提交到系统首次响应的时间。

调度层次

长程调度(Long-term scheduling)

  • 决定哪些作业被加载到内存中。
  • 控制多道程序的数量,影响系统负载。

中程调度(Medium-term scheduling)

  • 负责挂起或恢复进程,通常用于内存管理。

短程调度(Short-term scheduling)

  • 决定哪个进程获得 CPU,属于实时决策。
  • 调度频率高,需高效执行。

进程调度策略

  • 先来先服务(FCFS)
    • 按照进程到达的顺序进行调度。
      • 实现简单。
      • 可能导致“队头阻塞”,使短进程等待时间过长。
  • 短作业优先(SJF)
    • 优先调度预计运行时间最短的进程。
      • 能最小化平均等待时间。
      • 需要准确估算运行时间,可能导致“饥饿问题”。
  • 时间片轮转(Round Robin)
    • 分配固定时间片(Time Quantum)
      • 公平、适合交互式系统。
      • 时间片过短会增加切换开销,过长则退化为 FCFS。
  • 优先级调度(Priority Scheduling)
    • 根据优先级高低选择进程调度。
      • 满足不同任务的优先级需求。
      • 可能导致低优先级进程“饥饿”。
  • 多级队列调度(Multilevel Queue Scheduling)
    • 将进程分成多个队列,每个队列有不同的优先级和调度策略。
  • 多级反馈队列调度(Multilevel Feedback Queue Scheduling)
    • 允许进程在不同队列间动态调整,根据其行为改变优先级。
  • 最短剩余时间优先(SRTF, Shortest Remaining Time First)
    • 抢占式版本的 SJF,优先执行剩余时间最短的进程。

进程同步

进程同步是指多个进程在共享资源时协调彼此的操作,以避免竞争条件、死锁或资源不一致等问题。

同步的目标

  • 互斥(Mutual Exclusion):确保同一时刻只有一个进程访问临界区。
  • 死锁避免(Deadlock Avoidance):防止进程永久等待资源。
  • 公平性(Fairness):确保每个进程都有机会访问资源。
  • 进度保证(Progress Guarantee):如果没有进程在临界区,则能迅速分配资源。

进程同步的经典问题

生产者-消费者问题

问题描述:生产者生产数据并放入缓冲区,消费者从缓冲区取数据,需保证缓冲区不溢出或空取。

解决方法

  • 信号量实现(使用 fullempty 和互斥锁 mutex)。
  • 条件变量和锁实现。

读者-写者问题

问题描述:多个读者可以同时读资源,但写者只能独占资源。

解决方法

  • 优先读者策略:读者可以抢占写者。
  • 优先写者策略:写者优先访问,避免饥饿。

哲学家进餐问题

问题描述:五位哲学家围坐圆桌,用餐时需拿起左右两边的筷子,可能导致死锁。

解决方法

  • 限制最多允许四个哲学家同时拿筷子。
  • 哲学家必须先拿左筷子再拿右筷子。

进程同步的实现方法

  1. 锁(Locks)
  • 互斥锁(Mutex)

    • 用于保证一个进程独占资源。

    • 示例操作:

      • lock(): 加锁。
      • unlock(): 解锁。
  • 读写锁(Reader-Writer Locks)

    • 允许多个读者同时访问资源,但写者需独占。
    • 示例操作:
      • read_lock()read_unlock()
      • write_lock()write_unlock()
  1. 信号量(Semaphore)

    • 定义:计数器,表示资源的可用数量。
    • 两种类型:
      • 计数信号量:值可大于 1。
      • 二值信号量:值为 0 或 1,类似互斥锁。
    • 操作:
      • P(S)(Wait):如果信号量值大于 0,减 1;否则等待。申请资源
      • V(S)(Signal):信号量值加 1,唤醒等待队列中的进程。释放资源
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    Semaphore full = 0;       // 表示缓冲区中已填充的槽位
    Semaphore empty = N;      // 表示缓冲区中空的槽位
    Semaphore mutex = 1;      // 用于互斥
    
    // 生产者
    P(empty);
    P(mutex);
    // 放入数据
    V(mutex);
    V(full);
    
    // 消费者
    P(full);
    P(mutex);
    // 取出数据
    V(mutex);
    V(empty);
    
  2. 条件变量(Condition Variables)

    • 用于线程间的信号传递。
      • wait(condition, mutex): 释放锁并等待条件变量。
      • signal(condition): 唤醒等待该条件变量的线程。
  3. 自旋锁(Spinlock)

    • 锁空闲时,进程会忙等待。
    • 适用于临界区很短且多核系统中。
  4. 管程(Monitors)

    • 高级同步机制,封装了共享资源、条件变量和方法。
    • 支持条件等待和条件唤醒。

进程通信

  • 管道

    • 普通管道

      • 特点
        • 单向通信。
        • 只能在具有亲缘关系的进程间使用(如父子进程)。
      • 操作
      • 创建:pipe() 系统调用。
      • 管道有两个文件描述符:
        • 读端:fd[0]
        • 写端:fd[1]
    • 命名管道

      • 特点

        • 双向通信。
        • 可用于无亲缘关系的进程。
        • 持久化存在,直到被删除。
      • 操作

        • 创建:mkfifomknod
        • 打开:open()
        1
        2
        3
        
        mkfifo myfifo   # 创建命名管道
        echo "Message" > myfifo  # 写入数据
        cat myfifo              # 读取数据
        
  • 消息队列

  • 共享内存

    • 特点
      • 最快的进程通信方式。
      • 允许多个进程共享同一内存段。
      • 需要同步机制(如信号量)保护共享数据。
  • 信号量(Semaphore)

  • 信号(Signal)

  • 套接字(Socket)

  • 文件(File-Based IPC)

进程优先级

进程优先级是一个数 值,用于表示进程在系统中的执行顺序。

PRI(系统优先级):默认优先级,无法修改

nice 值:-20 ~19(对系统优先级的修正)

  • 修改 nice 值
    • nice/renice
    • 进入 top 后按“r”–> 输入进程 PID–> 输入 nice 值

实时优先级 是操作系统中用于实时进程调度的一种高优先级机制,主要用于确保实时任务能够在规定的时间约束内得到处理。实时优先级的进程通常具有比普通进程更高的优先级,因此在调度时会被优先考虑。

nice 值越低,进程的优先级越高,获得更多的 CPU 时间;

反之,nice 值越高,进程的优先级越低,CPU 时间的分配就越少。

管理工具

img

进程

pidof 获取 pid

1
2
pidof <程序名>
pidof -x /usr/sbin/nginx

pstree 进程树

1
2
3
4
pstree -p			# 带pid
pstree -c			# 不压缩显示

# {}内的为线程

ps 进程状态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
ps aux

# a 所有
# u 显示所有者
# x 包括不链接终端的进程

-p pid #显示指pid的进程

# 查看进程的父子关系
ps auxf

prtstat 特定进程状态信息

psmisc 包

 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
prtstat [options] <PID>

prtstat 1

# 输出类似于 /proc/<pid>/status 中的信息,并包含有关进程资源使用情况、权限、线程等的详细信息。

root@loong:~# prtstat 1
Process: systemd                State: S (sleeping)
  CPU#:  1              TTY: 0:0        Threads: 1
Process, Group and Session IDs
  Process ID: 1           Parent ID: 0
    Group ID: 1          Session ID: 1
  T Group ID: -1

Page Faults
  This Process    (minor major):   134890       108
  Child Processes (minor major):  2535495      1183
CPU Times
  This Process    (user system guest blkio):  14.22   9.30   0.00   0.00
  Child processes (user system guest):       201.79 204.24   0.00
Memory
  Vsize:       23 MB     
  RSS:         14 MB                     RSS Limit: 18446744073709 MB
  Code Start:  0x628f1483d000            Code Stop:  0x628f14847b61
  Stack Start: 0x7ffc40dd9f60
  Stack Pointer (ESP):          0        Inst Pointer (EIP):          0
Scheduling
  Policy: normal
  Nice:   0              RT Priority: 0 (non RT)

nice/renice 优先级

1
2
3
nice -n <priority> <command>				# 以特定nice值运行命令

renice -n <priority> <pid>					# 更改进程的nice值

pgrep 条件查找 PID

1
2
3
4
5
6
7
8
9
pgrep [options] <pattern>

pgrep -at pts/1
# -t 指定终端
# -a 显示详细完整的进程信息
# -l 完整进程名
# -u 根据用户

pgrep -f ".*sshd.*"

top 实时显示系统的运行状况

1
2
3
4
5
top -n <num>		# 刷新几次
top -d <num>		# 刷新间隔(秒)
top -p <pid>
top -H				# 线程
top -b				# 所有进程
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
查看状态
[root@rocky9 ~]# top
top - 20:45:41 up 35 min,  1 user,  load average: 0.00, 0.00, 0.00
Tasks: 287 total,   1 running, 286 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.2 sy,  0.0 ni, 99.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   1743.4 total,    480.6 free,    826.2 used,    609.4 buff/cache
MiB Swap:   2064.0 total,   2064.0 free,      0.0 used.    917.3 avail Mem
字段解析
    us 用户空间 sy 内核空间 ni 调整 nice 时间   id 空闲
    wa 等待 IO 时间 hi 硬中断 si 软中断(模式切换) st 虚拟化消耗占比

image-20241119171106289

htop 交互式的系统监视工具

比传统的top命令更丰富的信息和功能,并以彩色方式展示进程列表,使得用户可以更直观地了解系统的运行 状态。

注意:htop 是增强版的 top 命令,在 centos 中来自于 epel 源

pmap 进程内存映射关系

1
2
3
4
pmap [options] <pid>

-p			# 显示路径
cat /proc/1134/maps

vmstat 监测系统的整体负载情况

监测系统的整体负载情况:

​ 了解系统的CPU、内存、磁盘、网络等性能指标,以及进程数量和状态等信息。

分析系统性能问题:

​ 通过观察系统的CPU使用率、内存占用、磁盘I/O等指标,快速定位系统的性能瓶颈,找到导致系统负载 过高、响应变慢等问题的原因。

监测系统的稳定性:

​ 通过连续监测系统的负载情况,识别出系统的周期性波动,以及系统负载变化的规律,从而更好地管理系 统资源,保证系统的稳定性

1
2
3
4
5
6
vmstat
-d # 磁盘
-D # 磁盘综合
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st gu
 2  0      0 2632984  53788 949184    0    0     8    14  108    0  0  0 100  0  0  0

lsof 查看进程打开文件

lsof:list open files

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
lsof
-p	# pid
-c  # 程序 
-u	# 用户
-n	# 不解析
-i	# 筛选
-t	# 只显示 pid

# 查看当前哪个进程正在使用此文件
lsof /var/log/messages

lsof -i : 80

# 查看进程打开文件
ll /proc/6037/fd/

kill 信号发送

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
1) SIGHUP 无须关闭进程而让其重读配置文件
2) SIGINT 中止正在运行的进程;相当于 Ctrl+c
3) SIGQUIT 相当于 ctrl+\
9) SIGKILL 强制杀死正在运行的进程, 可能会导致数据丢失, 慎用!
15) SIGTERM 终止正在运行的进程,默认信号
18) SIGCONT 继续运行
19) SIGSTOP 后台休眠

# 显示信号
kill -l 

fuser -ki -9 80/tcp

jobs,fg,bg 前后台任务

1
2
3
4
# 使程序停于后台
Ctrl+z
# 使程序后台运行
COMMAND &

image-20241119182708838

1
2
3
4
5
6
7
8
9
# 使用&将多命令置于后台运行
sleep 3 &
sleep 3 &
sleep 3 &
wait
# wait 会阻塞程序,等待所有后台执行完成
# 进程 ID(PID):指定要等待的特定进程。
# 作业 ID(Job ID):指定作业号(通常以 % 开头,如 %1)。
# 无参数:如果不指定任何参数,wait 会等待当前 Shell 中所有的后台任务完成。

内存

free 显示内存使用情况

1
2
3
4
free -h				# 友好显示

-s <num>			# 刷新间隔
-c <num>			# 刷新次数

清理缓存

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
/proc/sys/vm/drop_caches 中写入相应的修改值会清理缓存建议先执行 syncsync 命令将所有未写的系统缓冲区写到磁盘中包含已修改的 i-node已延迟的块 I/O 和读写映射文件)。执行 echo 123  /proc/sys/vm/drop_caches, 达到不同的清理目的


To free pagecache, use:
                  echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes, use:
                  echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes, use:
                  echo 3 > /proc/sys/vm/drop_caches
                 

CPU

uptime CPU负载

w 显示当前登录到系统的用户信息以及系统的负载情况

mpstat 用于监控多核CPU性能和使用情况

sysstat软件包

1
2
3
4
5
6
7
-P 0
-P 1
-P ALL
# 指定 CPU 核心

# 每 5 秒采集一次信息,共采集三次
mpstat -P ALL 5 3

磁盘

iostat 磁盘使用情况和磁盘性能的实时统计信息

sysstat 包

1
2
3
4
5
6
7
默认显示 CPU 信息和所有设备信息:iostat
只显示 CPU 的信息:iostat -c
每隔 2 秒显示一次设备统计信息,总共输出 3 次:iostat -d 2 3
每隔 2 秒显示一次 sda 及上面所有分区的统计信息,共输出 3 次:iostat -p sda 2 3
以 MB 为单位显示所有信息:iostat -m
显示指定硬盘信息:iostat -d sda
显示设备的详细信息:iostat -x sda

iotop 监视磁盘I/O使用状况

iotop 软件包

网络

iftop 显示网络带宽使用情况

iftop软件包在 epel-release源里面

1
2
3
4
5
iftop -nNP
-i	# 接口
-P	# 端口
-n	# 不解析 ip
-N	# 数字端口

nload 网络实时吞吐量

nload软件包在 epel-release源里面

1
-m # 所有设备

nethogs 查看进程网络带宽的使用情况

nethogs软件包在 epel-release源里面

iptraf-ng 图形窗口,网络监视工具

实时展示关于IP流量的各种信息。

综合监控

dstat

实时监测和报告系统的性能指 标,包括CPU、内存、磁盘I/O、网络等方面的使用情况。

image-20241119185650284

glances

1
glances

C/S模式

1
2
3
4
5
6
服务端配置,在 12 主机上进行服务端的部署
[root@rocky9 ~]# glances -s -B 10.0.0.12


新开一个终端,模拟客户端连接服务端
[root@rocky9 ~]# glances -c 10.0.0.12

cockpit 基于Web的Linux服务器管理工具

9090端口

计划任务

at计划任务,一次性任务

依赖于atd服务,需要启动才能实现at任务

at队列存放在/var/spool/at目录中,ubuntu存放在/var/spool/cron/atjobs目录下

作业执行命令的结果中的标准输出和错误以执行任务的用户身份发邮件通知给root

apt install at -y

1
2
3
4
5
6
7
8
9
# Ctrl+D 退出
at 0:05
at now+1min

# 任务列表
at -l

# 具体任务内容
at -c 1

cron计划任务,周期性任务

  • 每个用户都有专用的cron任务文件:/var/spool/cron/crontabs/USERNAME
  • 默认标准输出和错误会被发邮件给对应的用户,如:mage创建的任务就发送至mage的邮箱
  • root能够修改其它用户的作业
  • 用户的cron中默认 PATH=/usr/bin:/bin,如果使用其它路径,在任务文件的第一行加PATH=/path或 者加入到计划任务执行的脚本中
  • 第六个字段指定要运行的命令。 该行的整个命令部分,直至换行符或“%”字符,指定的shell执行,除非使用反斜杠(\)进行转义,否则该命令中的**“%”**字符将变为换行符,并且第一个%之后的所有数据将作为标 准输入发送到该命令。
1
2
3
4
5
6
/etc/crontab 		#添加系统级的 cron 任务,写在此文件中
/etc/cron.d/ 		#配置文件
/etc/cron.hourly/ 	#脚本
/etc/cron.daily/ 	#脚本
/etc/cron.weekly/ 	#脚本
/etc/cron.monthly/ 	#脚本

image-20241119193500044

1
2
3
4
5
6
7
8
特定关健字
    @yearly 	#每年 1 月 1 日执行一次,相当于 0 0 1 1 *
    @annually 	#每年 1 月 1 日执行一次,相当于 0 0 1 1 *
    @monthly 	#每月 1 日执行一次,相当于 0 0 1 * *
    @weekly 	#每周日执行一次,相当于 0 0 * * 0
    @daily 		#每天 0 时执行一次,相当于 0 0 * * *
    @hourly 	#每小时 0 分执行一次,相当于 0 * * * *
    @reboot 	#重启后执行一次
1
2
3
4
5
crontab -l		#列出所有任务
crontab -e		#编辑任务
crontab -r		#移除所有任务
crontab -i		#同-r 一同使用,以交互式模式移除指定任务
crontab -u		#管理特定用户的 cron, 仅 root 有权限操作

面试题:11月每天的6-12点之间每隔2小时执行/app/bin/test.sh

1
2
#在 6,8,10,12 点整共 4 次分别执行 test.sh
0 6-12/2 * 11 * /app/bin/test.sh