Ubuntu入门学习教程,从入门到精通, Ubuntu 22.04中的进程管理详解(15)

Ubuntu 22.04中的进程管理详解

进程管理是Linux系统管理的核心。一个进程是程序的一个执行实例,理解如何查看、控制和调度进程是任何Linux用户或管理员的必备技能。

1. Linux进程概述

1.1 进程的概念

知识点:

  • 进程: 是一个正在执行的程序实例。它不仅仅是程序代码,还包括程序当前的活动、一组资源(如打开的文件、处理器状态、内存地址空间等)。
  • 程序 : 是一个静态的文件,包含了一组指令,存储在磁盘上。当程序被加载到内存并开始执行时,它就变成了一个或多个进程。
    比喻:
  • 程序 = 食谱(静态的指令列表)。
  • 进程 = 按照食谱正在烹饪的菜肴(动态的、有状态的执行过程)。
1.2 程序和进程

知识点:

  • 一个程序可以同时对应多个进程。例如,多个用户可能同时运行同一个/bin/bash程序,但每个用户都有一个独立的bash进程。
  • 进程有生命周期:创建(fork)、执行(exec)、等待、终止(exit)。
1.3 进程的状态

知识点:

在Linux中,进程在其生命周期中会处于不同的状态。ps命令会显示这些状态的缩写:

  • R (Running/Runnable): 正在运行或在运行队列中等待运行。
  • S (Sleeping): 可中断的睡眠。进程正在等待某个事件完成(如等待用户输入、网络数据),可以被信号唤醒。
  • D (Uninterruptible Sleep): 不可中断的睡眠。通常在等待I/O操作(如磁盘读写),不能被信号唤醒。这保证了I/O操作的完整性。
  • T (Stopped/Traced) : 已停止。进程被暂停,通常是由于收到了SIGSTOP信号或正在被调试器跟踪。
  • Z (Zombie): 僵尸进程。进程已终止,但其父进程尚未读取其退出状态。僵尸进程几乎不占用系统资源,只是在进程表中保留一个位置。
  • X (Dead) : 已死。进程已从系统中移除(ps通常看不到此状态)。
1.4 进程的分类

知识点:

可以从不同角度对进程进行分类:

  • 按用户分类 :
    • 系统进程 : 由内核在系统启动时创建,负责管理底层硬件和系统服务(如kthreadd, systemd)。
    • 用户进程 : 由用户启动,用于执行特定任务(如bash, firefox, gcc)。
  • 按服务模式分类 :
    • 前台进程: 与终端关联,能接收用户输入。通常一次只能有一个前台进程。
    • 后台进程: 不与终端直接交互,在后台默默运行。
1.5 进程优先级

知识点:

Linux是一个多任务操作系统,CPU时间需要分配给多个进程。进程优先级决定了CPU调度器分配给它的处理时间的多少。

  • 优先级范围 : 通常是 -2019
  • 数值含义 : 数值越小,优先级越高-20是最高优先级,19是最低优先级。
  • Nice值 (NI) : 优先级通常用"Nice值"表示。普通用户只能降低自己进程的优先级(增大Nice值),只有root用户可以提高任何进程的优先级(减小Nice值)。
  • PR值 : pstop命令中显示的PR是内核的最终优先级值,它与Nice值有关,但不是简单的映射关系。

2. 进程状态监测

2.1 静态监控:ps 命令

知识点:
ps (Process Status) 命令用于查看当前时刻的进程快照。它有非常多的选项,最常用的组合是 ps auxps -ef
语法知识点:

  • ps aux: 使用BSD风格语法。
    • a: 显示所有终端上的所有进程。
    • u: 以用户为中心的格式显示(包括用户、CPU、内存使用率等)。
    • x: 显示没有控制终端的进程。
  • ps -ef: 使用System V风格语法。
    • -e: 显示所有进程。
    • -f: 显示完整格式列表。
      案例代码:
bash 复制代码
# 使用 ps aux 查看所有进程的详细信息
$ ps aux
# USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
# root         1  0.0  0.3  168736 11920 ?        Ss   10:00   0:01 /sbin/init splash
# user      1234  0.5  2.1  3000000 80000 ?        Sl   10:05   0:10 /usr/lib/firefox/firefox
# ...
# USER: 进程所有者
# PID: 进程ID (Process ID),唯一标识
# %CPU: CPU使用率
# %MEM: 内存使用率
# VSZ: 虚拟内存大小
# RSS: 驻留集大小,实际占用的物理内存
# TTY: 关联的终端,?表示无终端
# STAT: 进程状态 (R, S, D, T, Z等)
# START: 启动时间
# TIME: 累计CPU使用时间
# COMMAND: 启动进程的命令
# 使用 ps -ef 查看所有进程,更侧重于父子关系
$ ps -ef
# UID        PID  PPID  C STIME TTY          TIME CMD
# root         1     0  0 10:00 ?        00:00:01 /sbin/init splash
# user      1234  1100  0 10:05 ?        00:00:10 /usr/lib/firefox/firefox
# ...
# UID: 用户ID
# PID: 进程ID
# PPID: 父进程ID (Parent Process ID)
# C: CPU使用率
# STIME: 启动时间
# TTY: 终端
# TIME: CPU时间
# CMD: 命令
# 查找特定进程,例如查找所有 sshd 进程
$ ps aux | grep sshd
# root      1500  0.0  0.1  15000  5000 ?        Ss   10:01   0:00 /usr/sbin/sshd -D
# user      2500  0.0  0.2  16000  6000 pts/0    S+   10:30   0:00 ssh user@192.168.1.10
2.2 动态监控:top 命令

知识点:
top 命令提供了一个动态的、实时更新的视图,显示系统资源使用情况和进程列表。它是系统管理员进行性能分析的首选工具。
语法知识点:

  • 启动后,top会进入一个交互式界面。
  • 常用交互命令 :
    • M: 按内存使用率排序。
    • P: 按CPU使用率排序(默认)。
    • T: 按累计时间排序。
    • u: 跟踪特定用户的进程。
    • k: 杀死一个进程(需要输入PID)。
    • q: 退出top
    • 1: 切换显示单个CPU核心的详细信息。
      案例代码:
bash 复制代码
# 启动 top 命令
$ top
# top - 10:45:30 up 2 days, 15:20,  2 users,  load average: 0.15, 0.20, 0.10
# Tasks: 200 total,   1 running, 199 sleeping,   0 stopped,   0 zombie
# %Cpu(s):  5.0 us,  2.0 sy,  0.0 ni, 92.0 id,  1.0 wa,  0.0 hi,  0.0 si,  0.0 st
# KiB Mem :  8000000 total,  6000000 free,  1000000 used,  1000000 buff/cache
# KiB Swap:  4000000 total,  4000000 free,        0 used.  7000000 avail Mem
#
#   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
#  1234 user      20   0 3000000  80000  60000 S   5.0  1.0   0:10.15 firefox
#  5678 root      20   0   15000   5000   4000 S   0.5  0.1   0:00.05 systemd
# ...
# 顶部信息区:
# load average: 系统负载,1分钟、5分钟、15分钟内的平均任务队列长度
# Tasks: 进程总数、运行中、睡眠中、停止、僵尸
# %Cpu(s): CPU使用情况分解 (us用户空间, sy内核空间, niNice值, id空闲, wa等待I/O)
# KiB Mem/KiB Swap: 内存和交换分区使用情况
# 进程列表区:
# PR: 优先级
# NI: Nice值
# VIRT: 虚拟内存
# RES: 物理内存
# SHR: 共享内存
# S: 状态
# %CPU, %MEM: CPU和内存使用率
# TIME+: 累计CPU时间
2.3 查看进程树:pstree 命令

知识点:
pstree 命令以树状结构显示进程,清晰地展示了进程间的父子关系。
语法知识点:

  • -p: 显示进程ID。
  • -u: 显示用户切换。
  • -a: 显示命令行参数。
    案例代码:
bash 复制代码
# 显示当前用户的进程树
$ pstree
# 显示所有进程的PID和用户
$ pstree -p -u
# 示例输出:
# systemd(1)─┬─NetworkManager(678)───{NetworkManager}(681)
#             ├─sshd(1000)───sshd(1500)───bash(1501)───pstree(2500)
#             └─(sd-pam)
# systemd(1)是所有进程的父进程
# sshd(1000)是sshd(1500)的父进程
# bash(1501)是pstree(2500)的父进程
2.4 列出进程打开的文件:lsof 命令

知识点:
lsof (List Open Files) 是一个强大的工具,用于列出当前系统打开的文件。在Linux中,"一切皆文件",包括网络连接、管道、设备等。因此lsof功能非常强大。
案例代码:

bash 复制代码
# 列出所有进程打开的所有文件 (输出非常多)
$ sudo lsof
# 查看某个特定进程打开了哪些文件 (需要PID)
$ sudo lsof -p 1234
# 查看某个文件被哪个进程打开
$ sudo lsof /var/log/syslog
# 查看某个用户打开的所有文件
$ sudo lsof -u user
# 查看某个端口被哪个进程占用 (非常常用)
$ sudo lsof -i :22
# COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
# sshd    1000 root    3u  IPv4  20000      0t0  TCP *:ssh (LISTEN)
# sshd    1000 root    4u  IPv6  20001      0t0  TCP *:ssh (LISTEN)

3. 进程状态控制

3.1 调整进程优先级:nice 命令

知识点:
nice 命令用于在启动 一个新进程时,指定它的Nice值。
语法知识点:

  • nice -n <Nice值> <命令>
  • 如果不指定-n,默认Nice值为10
    案例代码:
bash 复制代码
# 以默认的Nice值10启动一个低优先级的进程
$ nice gzip large_file.tar
# 以更高的优先级(Nice值为-5)启动一个进程 (需要root权限)
$ sudo nice -n -5 ./my_cpu_intensive_app
# 以最低优先级启动一个进程
$ nice -n 19 find / -name "*.log"
3.2 改变运行进程优先级:renice 命令

知识点:
renice 命令用于修改一个正在运行 的进程的Nice值。
语法知识点:

  • renice <Nice值> -p <PID>
  • 普通用户只能增加Nice值(降低优先级)。
    案例代码:
bash 复制代码
# 首先用 ps 或 top 找到进程的PID,假设为 2500
$ ps aux | grep my_app
# 将PID为2500的进程的Nice值调整为15 (降低其优先级)
$ renice 15 -p 2500
# 将PID为2500的进程的Nice值调整为-5 (提高其优先级,需要root权限)
$ sudo renice -5 -p 2500
3.3 向进程发送信号:kill 命令

知识点:
kill 命令用于向指定的进程发送信号。虽然名字叫"kill",但它可以发送多种信号,不仅仅是终止信号。
语法知识点:

  • kill -<信号> <PID>
  • 常用信号:
    • 15 (SIGTERM): 优雅地终止信号。进程可以捕获此信号,在退出前完成清理工作。这是kill的默认信号。
    • 9 (SIGKILL): 强制终止信号。进程无法忽略,立即被内核终止。这是最后的手段。
    • 19 (SIGSTOP): 停止进程,类似于Ctrl+Z
    • 18 (SIGCONT): 继续运行已停止的进程。
      案例代码:
bash 复制代码
# 向PID为1234的进程发送默认的SIGTERM信号,请求其优雅退出
$ kill 1234
# 如果进程无响应,强制杀死PID为1234的进程
$ kill -9 1234
# 停止PID为5678的进程
$ kill -19 5678
# 继续运行PID为5678的进程
$ kill -18 5678
# 列出所有可用的信号
$ kill -l
3.4 通过名字杀死进程:killall 命令

知识点:
killall 命令可以根据进程名来发送信号,而不是PID。这在你知道进程名但不想先查找PID时很方便。
语法知识点:

  • killall -<信号> <进程名>
    案例代码:
bash 复制代码
# 优雅地杀死所有名为 firefox 的进程
$ killall firefox
# 强制杀死所有名为 sshd 的进程 (危险操作,需谨慎)
$ sudo killall -9 sshd
# 向所有名为 my_app 的进程发送停止信号
$ killall -19 my_app

4. 进程启动与作业控制

作业控制是Shell的一个功能,允许用户管理多个进程(作业),包括将它们在前台和后台之间切换。

4.1 进程的启动
  • 前台启动: 直接在终端输入命令,Shell会等待命令执行完毕,期间终端被占用。
  • 后台启动 : 在命令后添加 & 符号,Shell会立即返回,进程在后台运行。
    案例代码:
bash 复制代码
# 前台启动,终端被占用
$ sleep 300
# 后台启动,Shell立即返回,并给出作业号和PID
$ sleep 300 &
# [1] 3001
# [1]  表示作业号
# 3001  表示进程ID
4.2 进程的挂起

知识点:

在前台运行的进程可以通过按键 Ctrl+Z 挂起(暂停),并将其放入后台。
案例代码:

bash 复制代码
# 前台启动一个进程
$ sleep 300
# 按下 Ctrl+Z
# ^Z
# [1]+  Stopped                 sleep 300
# 进程被挂起,并放入后台作业列表
4.3 使用 jobs 命令显示任务状态

知识点:
jobs 命令用于显示当前Shell会话中的所有后台作业。
案例代码:

bash 复制代码
$ jobs
# [1]+  Stopped                 sleep 300
# [2]-  Running                 ping google.com &
# [1]+ 表示最近的一个作业
# [2]- 表示次近的一个作业
# Stopped 表示被挂起
# Running 表示正在后台运行
4.4 使用 fg 命令将任务移至前台

知识点:
fg (foreground) 命令可以将后台作业调到前台继续运行。
案例代码:

bash 复制代码
# 将最近的后台作业(作业号1)调到前台
$ fg %1
# 或者直接 fg (默认调最近的)
$ fg
# sleep 300 进程会重新在前台运行
4.5 使用 bg 命令将任务移至后台

知识点:
bg (background) 命令可以将一个被挂起的作业在后台继续运行。
案例代码:

bash 复制代码
# 假设 sleep 300 已被 Ctrl+Z 挂起
$ jobs
# [1]+  Stopped                 sleep 300
# 让它在后台继续运行
$ bg %1
# [1]+ sleep 300 &
$ jobs
# [1]+  Running                 sleep 300 &
4.6 使用 nohup 命令启动脱离终端运行的任务

知识点:
nohup (No Hang Up) 命令可以让进程忽略SIGHUP信号(挂断信号,通常在终端关闭时发送给其子进程)。这使得进程在你退出Shell后仍能继续运行。其输出通常会重定向到 nohup.out 文件。
案例代码:

bash 复制代码
# 启动一个长时间运行的脚本,并使其在终端关闭后依然运行
$ nohup ./my_long_running_script.sh &
# 输出:
# nohup: ignoring input and appending output to 'nohup.out'
# 即使你关闭了SSH连接,脚本也会继续在服务器上运行
# 你可以重新登录后,用 ps aux | grep my_long_running_script.sh 来查找它

5. 本章小结

本章详细讲解了Ubuntu 22.04中进程管理的方方面面。我们从进程的基本概念(状态、分类、优先级)入手,学习了如何使用 ps, top, pstree, lsof 等工具来监控进程状态。接着,我们掌握了如何使用 nice, renice, kill, killall 来控制进程的优先级和生命周期。最后,我们探讨了Shell的作业控制功能,包括前后台任务的切换和使用 nohup 运行持久化任务。

掌握这些知识点和命令,是成为一名高效的Linux用户或管理员的必经之路,它将赋予你精确控制和洞察系统运行状态的能力。

相关推荐
zfj3212 小时前
Linux内核和发行版的的区别、职责
linux·运维·服务器·内核·linux发行版
0和1的舞者2 小时前
SpringAOP详解(二)
学习·spring·切面·代理·知识·springaop
leoufung2 小时前
LeetCode 120. Triangle:从 0 分到 100 分的思考过程(含二维 DP 与空间优化)
linux·算法·leetcode
iiiiii112 小时前
TD(λ),资格迹(Eligibility Traces)与时序差分学习的统一
人工智能·学习·机器学习·强化学习·rl
`林中水滴`2 小时前
Linux Shell 命令:nohup、&、>、bg、fg、jobs 总结
linux·服务器·microsoft
走在路上的菜鸟2 小时前
Android学Flutter学习笔记 第一节 Android视角认知Flutter(View,intent,Async UI)
android·学习·flutter
最后一个bug3 小时前
当linux触发panic后进行自定义收尾回调处理
linux·服务器·系统架构·bug
坚持学习前端日记3 小时前
个人运营小网站的最佳策略
java·学习·程序人生·职场和发展·创业创新
崇山峻岭之间3 小时前
Matlab学习记录20
开发语言·学习·matlab