一、进程相关的基本概念

1. 中断

  • 软中断:程序运行过程中,如果需要完成某些特权操作,它就必须向内核申请调用,由内核去判定此操作是否合规,一旦内核通过此申请,此调用功能就将由内核代理并在CPU上运行,此时进程只需等待调用返回即可,待返回结果后即可奔赴下一个流程

2. 进程的模式转换

进程的运行有两个模式,运行自己可执行的代码时叫做用户模式,一旦发生软中断,就会由内核代为执行这段代码段,而由内核代为执行的就叫做内核模式,一个进程运行过程中,可能会不断在两个模式中切换

3. task struct

任务结构体,内核为每一个运行在当前系统上的进程都会创建一个元数据结构,用来保存当前进程的元数据信息,比如运行时长、当前被调度到哪个核心上、占据内存空间等信息,而任务结构体就是为了让内核可以实时追踪到这些信息创建的,多个task struct组成的链接叫做task list

4. 进程的生命周期

  • 进程创建:内核初始化完成后,由内核创建第一个进程,通常称为init进程,至此,也就意味着代码执行的内核空间和用户空间已经创建完毕了,后续的所有用户空间的管理工作就由init来完成了,init不能代替内核完成系统调用等一切特权指令的执行,但是像创建进程这样的操作需要由init向内核提交,所以init进程是负责用户空间管理进程的进程,每一个进程都是由init进程或其父进程通过一个系统调用frok()创建的
  • 进程终止:任何父进程创建的子进程都要由其父进程销毁
  • Cow机制:写时复制机制,父进程通过frok( )创建子进程后,这时子进程与父进程使用同一段内存空间,一旦子进程需要修改数据,内核会重新分配一段内存空间给子进程,父进程通过clone( )把数据复制之,子进程在新的内存空间修改数据,这种机制就叫做Cow,写时复制,如果一个进程不需要写数据,那么同父进程读同一段地址空间也无所谓,但假如需要写数据,就必须创建新的,写时才复制,进程通过这种方式创建与销毁进程的代价会大大降低

5. 进程优先级

通过进程的优先级机制,来判断当cpu空闲时,优先将哪个进程调度到cpu上运行

5.1 优先级等级设计

linux将优先级分为140个等级,每个等级对应着两个队列,分为运行队列和过期队列,首先,内核从高到低进行扫描运行队列,将优先级最高的调度到cpu上运行,运行完毕后在将此进程调度到同等级的过期队列中,过期队列里存放被调度过一次并等待下一次调度的进程,等运行队列里的进程都运行完毕后,再将两个队列调换位置,继续调度

  • 实时优先级:0-99,数字越大,优先级越高
  • 静态优先级:100-139,数字越小,优先级越高,此级别优先级用户可以调整

5.2 优先级的Nice值

可以通过调整进程的nice值调整优先级,取值范围是-20到19,分别对应着静态优先级中的100-139,普通用户只能将自己启动的进程优先级调低

5.3 抢占式多任务工作模式

虽然说进程调度是基于优先级的,但是优先级较高的进程可以抢占优先级较低进程的cpu时间片,当然也不是随时能抢,在运行的过程中,进程有几个可以抢占的时间点,其他进程可以在这几个时间点去抢占,当然,如果没有进程抢占,那么这个进程就可以将分配的时间片用完

6. 保存现场、恢复现场

为了能保证系统多任务并行,内核就会基于cpu时间片切割机制,不断将进程调度到cpu上运行,但是进程在运行时,势必会产生很多中间数据,我们必须要将进程当前的运行状态保存下来,而进程的当前状态一般在寄存器中,一旦要调度下cpu,内核就需要找个地方将数据保存起来,这个操作就叫做保存现场,等过一段时间,在将此进程调度上来时,同时也需要将它刚才的运行状态也恢复,这就叫恢复现场

7. 进程内存管理

  • 虚拟内存实现机制:现代计算机系统中,内存空间都是虚拟的,内核把内存分配成固定大小的片段,每个片段叫页框(page frame),大小为4K,将空闲的页框分配给进程使用,这些分配的页框极有可能是不连续,是拼凑起来的,所以内核就加一个中间层,把它们逻辑组织成连续的空间,从进程的角度看并使用的空间叫进程的线性地址空间,而真正使用内存空间叫物理地址空间,对linux来说,虚拟内存是整个内核代码中最复杂的一部分
  • MMU:(Memory Management Unit)内存管理单元。主要维护线性地址空间与物理地址空间的对应关系,进程访问自己的线性地址时,都是通过MMU去取真正的物理地址中的数据返回给进程
  • LRU算法:当物理内存不足的时候,内核就会根据LRU算法(最近最少使用算法)把物理内存的数据挪到交换分区,等进程用到被交换的数据时,内核在根据LRU算法挪出物理空间,将原先交换出去的数据调度到物理内存中,但是新挪到物理内存的数据就会用到新的地址空间,也就意味着之前的线性地址空间与物理地址空间的对应的关系被破坏了,这将由MMU重新进行映射
  • 常驻内存集、虚拟内存集:一般来将,进程使用的内存空间中,数据是被可以交换到交换分区的,但是不能把进程的指令交换到交换分区,像指令数据就必须在内存中,这种不可以被交换到交换分区的数据组成的空间叫做常驻内存集,可以被交换出去的数据所组成的空间叫做虚拟内存集。
  • 缺页异常:当进程访问数据时,如被访问的数据被已经被交换到交换分区中或没有从文件载入时,这种异常就叫做缺页异常,有大异常和小异常之分

8. 进程间通信(IPC)

Inter-Process Communication,每一个进程运行时都以为只有自己和内核运行在系统中,但是必要时进程和进程之间要通信

8.1 同一主机间进程通信

  • singal:信号,可以通过发信号的方式进程通信
  • shm:(shared memory),共享内存,指定一段内存空间,一个进程向其中存数据,一个进程从中读数据

8.2 不同主机进程间通信

  • rpc机制:(remote procecure call)远程过程调用,类似库调用,只不过这里调用的函数不是本机的,而是另外一台主机的,另外一台主机将执行结果返回
  • socket:套接字

9. 进程类型

9.1 分类一

  • 守护进程:daemon,跟终端无关,系统开机时启动的进程,类似windows的服务
  • 前台进程:跟终端相关,通过终端启动的进程,也可把前台的进程变为以守护模式运行

9.2 分类二:按资源需求分类

  • CPU-Bound:需要cpu资源多,此类进程应该多分配cpu
  • IO-Bound:需要IO资源多,但是IO类型的进程应该比CPU-Bound类型的进程优先级高一些

10. 进程状态

  • 运行态:running,处于运行状态的
  • 就绪态:ready,可以运行但正在等待cpu调度的状态
  • 睡眠态:
    • 可中断睡眠:interruptable,可立即叫醒被调度到cpu运行的
    • 不可中断睡眠:uninterruptable,比如进程正在运行,等待数据I/O,数据没有I/O完毕,即使中断进程的睡眠,进程也没有数据可加工
  • 停止态:stopped,暂停中的,但不会被调度,除非手动启动
  • 僵死态:zombie,进程完成了指定任务,等待其父进程回收资源等操作的状态

二、配置文件

linux系统中/porc目录是用来保存进程运行状态信息的,而每个进程运行的状态信息,均保存在这个进程以其进程号命名的目录

  • /proc/PID/maps:保存此PID号进程的线性内存地址与物理内存空间的映射关系
  • /proc/PID/cmdline:保存此PID进程的详细运行命令是哪个

三、进程管理命令

1. ps命令

显示当前当前系统上进程状态的快照,输出的为静态信息,意思是说在执行ps命令时,立刻读取了当前进程运行的状态信息并且退出(report a snapshot of the current processes)
命令格式:ps [options]

  • 常用组合1
aux
u:以用户为中心,组织进程状态信息显示
x:所有与终端无关的进程
a:与终端相关的进程

命令输出输出信息:

USER:进程的属主
PID:当前进程的进程号
%CPU:运行时间所占据的CPU百分比
%MEM:占据总体内存空间的百分比
VSZ:virtual memory size,虚拟内存集,在线性地址当中真正占据的内存大小
RSS:resident size,常驻内存集大小
TTY:通过那个终端启动的
?:表示与终端无关
STAT:进程状态
R:running,运行中的
S:interruptable sleeping,可中断睡眠
D:uninterruptable sleeping不可终端睡眠
T:stopped,停止态
Z:zombie,僵死态
+:前台进程
l:多线程进程
N:低优先级进程
<:高优先级进程
s:session leader,会话的创建者
start:启动时间
time:占据cpu累计时长
command:由哪个命令启动,加[]表示内核线程
  • 常用组合2:
-ef
-e:显示所有进程
-f:显示完整格式的进程信息
输出信息
UID:进程的属主
PID:进程号
PPID:父进程的进程号,进程为0的进程是内核启动第一个进程,之后会把他终止,所以就看不到了
C:运行的cpu编号
TIME:cpu的累计时间
  • 常用组合3
-eFH、-ejH:
H:以层级格式显示进程
j:任务格式显示
F:更为完整格式
输出信息:
PSR:运行的cpu核心
  • 自定义组合
自定义组合需要结合-o选项,如ps axo pid,psr,command,显示结果中只会显示你关心的参数
常用的参数
ni:nice值
pri:优先级
psr:运行在哪颗cpu上
rtptrio:实时优先级
euid:有效用户
uuid:实际用户

2. kill命令

向进程发送控制信号,实现对进程的管理
命令格式:kill [option] [-signal|-p] [-q sigval] [-a] [--] pid...

option
-l:列出kill命令支持的信号
常用信号:
1:SIGHUP,在不终止进程的前提下,通知进程重读配置配件
2:SIGINT,终止正在运行的进程,相当于ctrl+c
9:SIGKILL,杀死正在运行的进程
15:SIGTERM,优雅关闭正在运行的进程
18:SIGCONT,继续运行
19:SIGSTOP,暂停运行,使进程处于停止态

信号指定方法

  • 信号的数字标识:直接使用数字,如1、2
  • 信号的完整名称:如SIGHUP、SIGINT
  • 信号的简写名称:如HUP、INT

3. killall命令

终止指定名称下的所有进程
命令格式:killall [-SIGNAL] program
program:指定程序名称

4. pgrep、pkill命令

pgrep完成进程显示过滤、pkill可以杀死指定的进程
命名格式:pgrep|pkill [options] pattern

option:
-u uid:匹配有效用户ID
-U uid:实际用户
-t terminal:与某终端相关
-l:显示进程名字
-a:显示完整格式的程序名
-P pid:显示指定进程的子进程

5. top命令

命令格式:top [option]

option
-d #:指定刷新间隔
-b:以批次方式显示
-n:结合-b选项,指定指显示几批
  • 排序方式内置快捷键
    M:根据内存排序
    T:累计占用cpu时长
    P:过去1次的刷新时间内,占据cpu百分比排序
    s:修改刷新时长
    k:杀死指定进程
  • 首行信息显示快捷键
    l:首行运行时间是否显示
    1:cpu详细信息
    t:task和cpu的显示格式
    m:显示内存信息
  • 顶部输出信息
    top:当前系统时间
    up:运行时长
    user:当前系统登录的用户数
    load average:过去1分钟、5分钟、15分钟的平均负载,cpu队列中等待运行任务的个数
    ------------------------
    Tasks:当前系统的进程数
    running:处于运行状态的进程数
    sleeping:睡眠状态的进程数
    stopped:停止状态的进程数
    zomble:僵死状态的进程数
    ------------------------
    us:用户空间程序占据的百分比
    sy:内核空间程序占据的百分比
    ni:调整nice占据的时间
    id:空闲比例
    wa:wait,等待I/O完成的时间
    hi:硬中断消耗的时间百分比
    si:软终端消耗的时间百分比
    st:被虚拟化技术偷走的时间
    ------------------------
    total:物理内存的总大小
    free:空闲内存总大小
  • 列表首行输出信息
    SHR:共享内存大小
    PR:优先级
    VIRT:虚拟内存集
    RES:常驻内存集
    NI:nice值
    S:当前运行状态
    %CPU:占据的cpu比例
    %MEM:占据的内存比例
    TIME+:累计运行时长

6. htop命令

htop命令较top命令功能要强大的多,进入命令后可按F1键获取帮助,以下列举几个常用的功能

  • 内置快捷键
F1:获取帮助
F2:更改显示风格或增减显示参数
F4:指定过滤关键字
F5:按树状形式显示
s:追踪光标指定进程发起的系统调用
l:显示光标指定进程打开的文件
a:设置进程与cpu的亲缘关系,意思是进程要是想运行,就必须运行在设置的某个cpu上

7. vmstat命令

用来显示虚拟内存的状态信息
命令格式:vmstat [options] [delay [count]]

option:
-s:内存状态
delay:延迟
命令输出信息意义
procs:运行、阻塞队列
r:等待运行的进程个数,对于非常繁忙的服务器,单颗CPU单核心等待超过三个,通常意味着CPU性能有点低了
b:处于不可中断睡眠进程的个数,被阻塞的队列的长度
memory:
swpd:交换内存的使用总量
free:物理内存的空闲总量
buffer:用于buffer的内存总量
cache:用于cache的内存总量
swap:
si:数据进入到swap的速率,单位是kb/s每秒
so:数据离开swap的速率
io:
bi:从块设备读入数据到内存的速率,kb/s
bo:从内存保存至块设备的速率,kb/s
system:
in:interrupts,中断速率
cs:context switch,上下文切换,进程切换需要保存现场恢复现场,太快的话会浪费大量的资源在切换上,
太慢的话又难以造成进程并行的假象
cpu:
us:用户空间占据的cpu的比例
sy:内核空间占据的cpu比例
id:空闲
wa:等待I/O
st:被虚拟化技术偷走的时间

8. dstat命令

命令格式:dstat [-afv] [options..] [delay [count]]

option
-c:只显示cpu信息
-d:只显示磁盘读写速率
-D sda:显示指定磁盘读写信息
-p:显示进程统计数据,有新创建进程信息
--top:显示最占用指定资源的进程
-cpu
-io
-mem
-int:中断
-latency:延迟最大的进程
输出信息
total-cpu-usage:cpu使用信息
dsk/total:磁盘读写速率
net/total:网络收发速率
paging:页面换进换出速率
system:中断和上下文切换速率
int:中断
csw:上下文切换

9. pmap命令

用于显示指定进程的内存映射表
命令格式:pmap [options] pid [...]

option
-x:扩展格式

10. glances命令

命令格式:glances [OPTIONS]

option
-s -B IPADDR:-s指定启用服务模式,-B指定监听的IP地址
-c IPADDR:连接主机地址
-b:以字节为单位显示网卡速率
-d:关闭磁盘I/O模块
-f /path/to/file:设置输出文件的位置和格式
-w:启用web模式,需要安装python-bottle
-t #:指定刷新时间

11. pidof命令

根据进程名获取pid
命令格式:pidof PID_NAME

12. pstree命令

已树状形式显示进程信息,安装命令的包是psmisc

四、进程优先级调整

nice值的取值范围是-19到20,分别对应100和139,普通用户只能将nice至调低,进程默认启动的nice值为0,优先级为120

1. nice命令

启动进程是以指定优先级运行
命令格式:nice [OPTION] [COMMAND [ARG]...]

option
-n #:更改优先级,默认为10

2. renice命令

改变运行状态进程的nice值
命令格式:renice [-n #] pid

3. 查看进程优先级

命令格式:ps axo pid,comm,ni

五、小tips

1. Big O算法

算法复杂度评价标准,当一个算法处理的数据增加时,与需要花费时间比值的走势
O(1):无论数据量多大,处理的时间是恒定的
O(LogN):刚开始急剧增加,慢慢平缓
O(n):与复杂度成正比
O(n^2):比O(n)低一级别
O(2^n):数据的微小增加,需要的时间急剧增大