Linux 进程管理

概述

本文介绍与进程、服务相关的若干知识。

进程

如果学习过操作系统课程,我们知道:程序是一组代码集合,它存储于硬盘之中,而进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。

在 Linux 系统中,进程可简单表示为:PID (进程编号) + PPID (父进程编号) + 基于使用者所得到的权限 + 程序码。

我们最常使用的 bash 就是一个进程,其上输入各种指令便会引发一个 bash 子进程以执行此指令。这里就简单说明单一 bash 环境下的工作管理 (job control):

  • 通过在指令尾部添加 &,该指令便会于 bash 背景中执行,执行完成后,其结果会显示于 bash 页面之上。
  • 向正在运行的指令程序输入 ctrl + z,该指令程序便会暂停执行,并位于 bash 背景之中。
  • 借助于指令 jobs,可查看 bash 背景中各工作的状态信息。
  • 借助于指令 fg,可将某指令程序拉至 bash 页面中执行。
  • 借助于指令 bg,可将背景中某指令程序状态由暂停变更为运行中。
  • 借助于指令 kill,可向背景中某指令程序发送特定 signal,以重启、删除此指令程序。

需要注意的是,如果 bash 关闭,则 bash 背景中各种指令程序随即停止。若不想此场景发生,可使用指令 nohup xxx &,如此该指令的执行便会位于系统背景之中,此时只有当 Linux 系统关闭,该指令程序才会停止。

接下来,我们简单谈谈 Linux 系统下的进程管理 (process control):

  • ps

    该指令可查看个时间点各进程的运行情况。

    通常只需知道两个选项即可:ps -l 用于查看 bash 之下的各进程运行情况,ps aux 用于查看系统之下的各进程运行情况。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
    0 S 1000 1689 1688 0 80 0 - 5032 do_wai pts/0 00:00:00 bash
    0 R 1000 2101 1689 0 80 0 - 5228 - pts/0 00:00:00 ps
    各字段含义如下:
    - F 表明此进程的权限类别,若为 4,则表示其为 root 权限。
    - S 表明此进程的运行状态,其取值通常有:R (运行中)、S (睡眠中,可被手动唤醒)、D (睡眠中,
    不可被手动唤醒,通常处于 I/O 等待)、T (停止中)、Z (僵尸状态,进程已终止,但无法被移除)
    - UID/PID/PPID,含义十分明确,忽略。
    - 表明此进程的 CPU 使用率。
    - PRI/NI 共同指明该进程的运行优先级,PRI 取值越低,进程运行优先级越高。
    PRI 动态变化且无法进行调整,由于 PRI 取值与 NI 相关,因此可动态调整它以间接调整 PRI。
    借助于 nice 指令,在程序运行之初即指定 NI;借助于 renice,重新调整特定进程的 NI。
    - ADDR 指明该进程所依据的程序位于内存哪部分,不知道为什么显示为 '-'
    - SZ 指明该进程目录用掉多少内存。
    - WCHAN 仍是指明该进程是否处于运行状态。
    - TTY 指明使用者所使用的伪终端设备。
    - TIME 指明该进程实际使用 CPU 的时间。
    - CMD 指明触发此进程运行的指令。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root 1 0.0 0.1 168896 12052 ? Ss 09:09 0:02 /sbin/init splash
    各字段含义如下:
    - USER 指明该进程的所属账号。
    - PID/%CPU/%MEM,含义十分明确,忽略。
    - VSZ 指明该进程用掉的虚拟内存量。
    - RSS 指明该进程占用的固定内存量。
    - TTY 含义同上。
    - STAT 指明该进程的运行状态,含义同 S。
    - START/TIME/MOMMAND,含义十分明确,忽略。

    通常情况下,当子进程运行完成后,父进程应当合理终止它。但是由于系统不稳定或者程序编写问题,会造成某些进程虽已运行完成,但是未被终止,这种进程便被称为 zombie process (即僵尸进程),其状态便为 Z

  • top

    该指令可动态持续侦测各进程的运行情况。

    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
    top - 10:59:28 up  1:49,  2 users,  load average: 0.27, 0.30, 0.24
    Tasks: 247 total, 1 running, 245 sleeping, 1 stopped, 0 zombie
    %Cpu(s): 0.0 us, 1.5 sy, 0.0 ni, 98.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
    MiB Mem : 7929.7 total, 6317.6 free, 409.2 used, 1202.9 buff/cache
    MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 7222.2 avail Mem

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    860 root 20 0 1120560 46824 26060 S 0.6 0.6 0:54.76 containerd
    top 指令输出结果比较多,我们一行一行介绍:
    第一行:
    10:59:28 指明当前时间;up 1:49 指明自开机至此的系统运行时间;2 users 指明系统使用者个数;
    load average: xxx 指明 1/5/15 分钟内的平均负载情况 (即系统平均需要运行几个进程)。
    第二行:
    各字段含义比较清晰,指明系统共计多少进程,多少处于运行状态,多少处于运行状态,...。
    第三行:
    该行从各个方面总体评估 CPU 的使用情况,即哪些方面占用了多少 CPU。
    us(user) 表示用户空间的 CPU 使用情况;sy(system) 表示系统空间的 CPU 使用情况;
    ni(niceness) 表示修改过优先级的进程的 CPU 使用情况;id(idle) 表示空闲 CPU 的使用情况;
    wa(wait) 表示 I/O 等待的 CPU 使用情况;hi(hard interrupt) 表示硬中断的 CPU 使用情况;
    si(soft interrupt) 表示软中断的 CPU 使用情况;
    st(stole time) 表示分配给当前虚拟机的 CPU 时间中,被本机其他虚拟机所偷用的 CPU 使用情况。
    第四行:
    各字段含义比较清晰,指明系统的内存总量、空闲内存量、已用内存量和用作 buff 的内存量。
    第五行:
    与第四行各字段类似,只不过指的是内存交换空间的相关指标。
    第六行:
    PR 与上方的 PRI 同义;VIRT 指明该进程所用的内存总量,包括 Mem + Swap;
    RES 指明该进程真实使用的 Mem 之中的内存量;SHR 指明该进程所用的共享内存量;

    默认情况下,指令 top 以 PID 排序侦测结果。若需按照内存使用率或 CPU 使用率进行排序,可在侦测页面中输入 MC

  • pstree

    该指令能够将各进程按照父子关系组织成为一棵树。

    1
    2
    3
    4
    5
    systemd─┬─ModemManager───2*[{ModemManager}]
    ├─ ***
    ├─sshd───sshd───sshd───bash─┬─pstree
    │ └─vim
    ├─ ***

    从中可以看到进程 systemd 为所有进程的唯一父进程。

  • kill/killall

    该指令可向特定进程发送特定 signal,以启动、终止、重启该特定进程。

    常见 signalSIGHUP (启动被终止的进程)、SIGKILL (强制终止进程)、SIGSTOP (暂停进程)。

最后简单介绍若干查看系统资源的指令:

  • free –> 查看系统内存使用情况。
  • uname –> 查看系统与核心相关参数信息。
  • uptime –> 查看系统启动时间与工作负载情况。
  • netstat –> 查看网络与 port 使用的相关信息。
  • dmesg –> 查看核心所产生的讯息。
  • vmstat –> 动态侦测系统资源的使用情况。

服务

服务,通常也称为 “daemons”,即一直处于运行状态的进程,它能向外界提供一种功能。

在此,我们介绍两种服务,一种与例行性工作调度相关,一种与日志记录相关。

在 Linux 系统中,存在两种例行性工作调度:突发型 (即某个特定时间点执行,它借助于 atd 服务而存在,使用指令 at 可定义此类任务)、循环型 (即定期执行,它借助于 crond 服务而存在,使用指令 crontab 可定义此类任务)。

对于 atcron 而言,分别存在 xx.allowxx.deny 以限制所定义的任务是否可被执行,另外使用者所创建的任务分别被放置于 /var/spool/at/var/spool/cron 之中。

值得说一下的是:crond 服务通常也为系统所使用,在 /etc/crontab 配置文件中,其中定义了若干周期性执行 /etc/cron.d/* 中脚本 (其脚本功能可能是更新 locate 数据库,也可能是轮替日志文件) 的任务。

另外,考虑一种场景:假定某任务每周日晚上执行,但是某周六系统停电,电脑关机,自然该任务这周日不会执行。周一启动系统后,时间已经过期,crond 自然会等到本周日晚上才执行此任务,然而如果该任务比较重要的话,最好还是周一就执行一次。为解决这个问题,anacron 进程被启用,它会自动判断哪些任务逾期未执行,然后自动执行它们。

十分有意思的是:anacroncrond 控制而周期执行,anacron 又会反过来判断各任务是否逾期未完成。

在 Linux 系统中,日志记录主要分为两部分:一部分由 systemd-journald 提供,系统启动之初的各种日志信息均会由此记录;一部分由 rsyslog 提供,它会记录系统运行期间各进程的日志信息,普通程序也可基于相关规范将日志信息发与 rsyslog 以供其管理。

各种日志文件通常均位于 /var/log 之中。

随着系统的运行,日志文件将会越来越大,那么就存在 logrotate 这一服务,它会基于 /etc/logrotate.conf/etc/logrotate.d/* 中配置文件内容,按照特定方式轮替日志文件 (以某种格式备份当前所用日志文件,随后清空当前所用日志文件。另外,过早的日志文件可能会被自动清除)。