1. 进程基础知识

1.1 程序,进程,守护进程,线程

程序:磁盘上的文件。 进程:运行着的程序。 守护进程:持续运行的进程。 子进程/线程:由进程产生的进程。 生产查进程:ps -aux | ps -ef


1.2 父进程,子进程

image.png

当父进程接收到任务调度时,会通过fock派生子进程来处理,那么子进程会继承父进程属性。

  1. 子进程在处理任务代码时,父进程会进入等待状态中…
  2. 子进程在处理任务代码后,会执行退出,然后唤醒父进程来回收子进程的资源。
  3. 如果子进程在处理任务过程中,父进程退出了,子进程没有退出,那么 这些子进程就没有父进程来管理了,孤儿进程。

    PS: 每个进程都父进程的PPID,子进程则叫PID。

    僵尸进程:一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出。这个子进程就是僵尸进程。任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。

2.监控进程状态

程序在运行后,我们需要了解进程的运行状态。查看进程的状态分为: 静态和动态两种方式

2.1 ps(静态)显示进程状态

1) 示例、ps -aux(详细状态) 常用组合,查看进程 用户、PID、占用cpu百分比、占用内存百分比、状态、执行的命令等
image.png

ps -ef 查看的是:UID PID PPID C STIME(运行时长) TTY TIME CMD

2.2 状态信息详解

状态 描述
USER 启动进程的用户
PID 进程运行的ID号
%CPU 进程占用CPU百分比
%MEM 进程占用内存百分比
VSZ 进程占用虚拟内存大小 (单位KB)
RSS 进程占用物理内存实际大小 (单位KB)
TTY 进程是由哪个终端运行启动的。 tty1-tty6是本机上面的登入者进程,若为pts/0等,则表示为由网络连接进主机的进程;?表示内核程序与终端无关
STAT 进程运行过程中的状态 man ps (/STATE)
START 进程的启动时间
TIME 进程占用 CPU 的总时间(为0表示还没超过秒)
COMMAND 程序的运行指令,[ 方括号 ] 属于内核态的进程。 没有 [ ] 的是用户态进程。

优化系统最关键的就是保证CPU\内存被正确的利用

  1. 对查找的指定列排序:
  2. ps -eo "%C : %p : %z : %a" --sort -vsz
  3. ps -eo "%C : %p : %z : %a" --sort +%cpu
  4. ps -eo "%C : %p : %z : %a" --sort +pid
  5. 对查找的树状结构显示:
  6. [root@oldboy ~]# pstree
  7. systemd─┬─NetworkManager───2*[{NetworkManager}]
  8. ├─VGAuthService
  9. ├─abrt-watch-log
  10. ├─abrtd
  11. ├─agetty
  12. ├─auditd───{audi

2.3 STAT(进程)状态

STAT基本状态 描述 STAT状态+符号 描述
R 进程运行 s 进程是控制进程, Ss进程的领导者,父进程
S 可中断睡眠 < 进程运行在高优先级上,S<优先级较高的进程
T 进程被暂停 N 进程运行在低优先级上,SN优先级较低的进程
D 不可中断睡眠 + 当前进程运行在前台,R+该表示进程在前台运行
Z 僵尸进程 l 进程是多线程的,Sl表示进程是以线程方式运行
  1. 案例一、PS命令查看进程状态切换
  2. #1.在终端1上运行vim
  3. [root@xuliangwei ~]# vim oldboy
  4. #2.在终端2上运行ps命令查看状态
  5. [root@xuliangwei ~]# ps aux|grep oldboy #S表示睡眠模式,+表示前台运行
  6. root 58118 0.4 0.2 151788 5320 pts/1 S+ 22:11 0:00 oldboy
  7. root 58120 0.0 0.0 112720 996 pts/0 R+ 22:12 0:00 grep --color=auto oldboy
  8. #在终端1上挂起vim命令,按下:ctrl+z
  9. #3.回到终端2再次运行ps命令查看状态
  10. [root@xuliangwei ~]# ps aux|grep oldboy #T表示停止状态
  11. root 58118 0.1 0.2 151788 5320 pts/1 T 22:11 0:00 vim oldboy
  12. root 58125 0.0 0.0 112720 996 pts/0 R+ 22:12 0:00 grep --color=auto oldboy
  13. 案例二、PS命令查看不可中断状态进程
  14. #1.使用tar打包文件时,可以通过终端不断查看状态,由S+,R+变为D+
  15. [root@xuliangwei ~]# tar -czf etc.tar.gz /etc/ /usr/ /var/
  16. [root@xuliangwei ~]# ps aux|grep tar|grep -v gre
  17. root 58467 5.5 0.2 127924 5456 pts/1 R+ 22:22 0:04 tar -czf etc.tar.gz /etc/
  18. [root@xuliangwei ~]# ps aux|grep tar|grep -v grep
  19. root 58467 5.5 0.2 127088 4708 pts/1 S+ 22:22 0:03 tar -czf etc.tar.gz /etc/
  20. [root@xuliangwei ~]# ps aux|grep tar|grep -v grep
  21. root 58467 5.6 0.2 127232 4708 pts/1 D+ 22:22 0:03 tar -czf etc.tar.gz /etc/

2.2 top(动态)显示系统状态

(显示系统中各个进程的资源占用状况) 从第七行开始,给出的是各进程(任务)的状态监控。
image.png

2.4.1 top 常见指令

字母 功能
h 查看帮出
1 数字1,显示所有CPU核心的负载
z 以高亮显示数据
b 高亮显示处于R状态的进程
M 按内存使用百分比排序输出
P 按CPU使用百分比排序输出
q 退出top

2.2.1 top 状态详解

任务 含义
Tasks: 129 total 当然进程的总数
1 running 正在运行的进程数
128 sleeping 睡眠的进程数
0 stopped 停止的进程数
0 zombie 僵尸进程数
%Cpu(s): 0.7 us 系统用户进程使用CPU百分比
0.7 sy 内核中的进程占用CPU百分比,通常内核是于硬件进行交互( 比如 网卡、硬件设备、硬盘 )
ni 优先级进程占比
us 用户进程占用cpu百分比( 视频加密、视频解码 )
98.7 id 空闲CPU的百分比 ( 值越大、说明服务器越空闲 )
0.0 wa CPU等待IO完成的时间
0.0 hi 硬中断,占的CPU百分比
0.0 si 软中断,占的CPU百分比
0.0 st 比如虚拟机占用物理CPU的时间


2.2.2 中断**

  1. 1.什么是中断
  2. 中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求。
  3. 2.为什么要有中断呢? "举个生活中的例子"
  4. 比如说你订了一份外卖,但是不确定外卖什么时候送到,也没有别的方法了解外卖的进度,但是,配送员送外卖是不等人的,到了你这儿没人取的话,就直接走人了。
  5. 所以你只能苦苦等着,时不时去门口看看外卖送到没,而不能干其他事情。
  6. 不过呢,如果在订外卖的时候,你就跟配送员约定好,让他送到后给你打个电话,那你就不用苦苦等待了,就可以去忙别的事情,直到电话一响,接电话、取外卖就可以了。
  7. 这里的“打电话”,其实就是一个中断。 没接到电话的时候,你可以做其他的事情;只有接到了电话(也就是发生中断),你才要进行另一个动作:取外卖。
  8. 这个例子你就可以发现,中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力。节省时间提高效率
  9. 3.中断会带来什么问题?
  10. 由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行。
  11. 如果中断本身要做的事情不多,那么处理起来也不会有太大问题;但如果中断要处理的事情很多,中断服务程序就有可能要运行很长时间。
  12. 特别是,中断处理程序在响应中断时,还会临时关闭中断。这就会导致上一次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失。
  13. 那么还是以取外卖为例:假如你订了 2 份外卖
  14. 一份主食和一份饮料,并且是由 2 个不同的配送员来配送。这次你不用时时等待着,两份外卖都约定了电话取外卖的方式。但是,问题又来了。
  15. 当第一份外卖送到时,配送员给你打了个很长的电话,商量发票的处理方式。与此同时,第二个配送员也到了,也想给你打电话。
  16. 但是很明显,因为电话占线(也就是关闭了中断响应),第二个配送员的电话是打不通的。所以,第二个配送员很可能试几次后就走掉了(也就是丢失了一次中断)。
  17. 4.系统软中断
  18. 如果你弄清楚了“取外卖”的模式,那对系统的中断机制就很容易理解了。
  19. 事实上,为了解决中断处理程序执行过长和中断丢失的问题,Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:
  20. 上半部用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关工作。
  21. 下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行。
  22. 比如说前面取外卖的例子,上半部就是你接听电话,告诉配送员你已经知道了,其他事儿见面再说,然后电话就可以挂断了;
  23. 下半部才是取外卖的动作,以及见面后商量发票处理的动作。
  24. 这样,第一个配送员不会占用你太多时间,当第二个配送员过来时,照样能正常打通你的电话。
  25. 5.接下来在看一个例子?
  26. 除了取外卖,我再举个最常见的网卡接收数据包的例子,让你更好地理解。
  27. 网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。
  28. 对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),
  29. 最后再发送一个软中断信号,通知下半部做进一步的处理。
  30. 而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。
  31. 所以,这两个阶段你也可以这样理解:
  32. 上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行;
  33. 而下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行。
  34. Linux软中断与硬中断小结
  35. Linux 中的中断处理程序分为上半部和下半部:
  36. 上半部对应硬件中断,用来快速处理中断。
  37. 下半部对应软中断,用来异步处理上半部未完成的工作。
  38. Linux 中的软中断包括网络收发、定时、调度、等各种类型,可以通过查看 /proc/softirqs 来观察软中断的运行情况。
  39. PS经常听同事说大量的网络小包会导致性能问题,为什么呢?
  40. 因为大量的网络小包会导致频繁的硬中断和软中断?所以大量网络小包传输很慢,但如果将网络包一次传递,是不是会快很多呢?

3. 进程管理

3.1 管理进程状态

当程序运行为进程后,如果希望停止进程,怎么办呢? 那么此时我们可以使用linux的kill命令对进程发送关闭信号。当然除了kill、还有killall,pkill

使用kill -l列出当前系统所支持的信号
虽然linux支持信号很多,但是我们仅列出我们最为常用的3个信号

数字编号 信号含义 信号翻译
1 SIGHUP 通常用来重新加载配置文件
9 SIGKILL 强制杀死进程
15 SIGTERM 终止进程,默认kill使用该信号

1.我们使用kill命令杀死指定PID的进程。

#1.给 vsftpd 进程发送信号 1,15
[root@xuliangwei ~]# yum -y install vsftpd
[root@xuliangwei ~]# systemctl start vsftpd
[root@xuliangwei ~]# ps aux|grep vsftpd

#2.发送重载信号,例如 vsftpd 的配置文件发生改变,希望重新加载
[root@xuliangwei ~]# kill -1 9160

#3.发送停止信号,当然vsftpd 服务有停止的脚本 systemctl stop vsftpd
[root@xuliangwei ~]# kill 9160

#4.发送强制停止信号,当无法停止服务时,可强制终止信号
[root@xuliangwei ~]# kill -9 9160

2.Linux系统中的killall、pkill命令用于杀死指定名字的进程。
我们可以使用kill命令杀死指定进程PID的进程,如果要找到我们需要杀死的进程,我们还需要在之前使用ps等命令再配合grep来查找进程,
------------>>>   而killall、pkill把这两个过程合二为一,是一个很好用的命令。
#例1、通过服务名称杀掉进程
[root@xuliangwei ~]# pkill nginx   或:
[root@xuliangwei ~]# killall nginx

#例2、使用pkill踢出从远程登录到本机的用户,终止pts/0上所有进程, 并且bash也结束(用户被强制退出)
[root@xuliangwei ~]# pkill -9 -t pts/0

kill -9 可能导致进程崩溃,服务崩溃。。特别是有数据的服务,尽量不用。 mysql数据库进程,oracle数据库进程永远不要用-9

PS: 非常重要的概念:

优雅重启: 不影响客户访问。 ngixn -s reload | apchectl graceful |  mysql shutdown  ... 1.阻止新用户访问。 2.继续服务老用户。

服务管理: centos7以前: service:服务启动
service crond stop ==/etc/init.d/crond stop service crond start==/etc/init.d/crond start chkconfig:设置开机自启动 chkconfig crond off #停止开机自启动 chkconfig crond on #开机自启动 chkconfig —list #查看哪些服务开机自启动

4. 后台管理

4.1什么是后台进程

通常进程都会在终端前台运行,一旦关闭终端,进程也会随着结束,
那么此时 即使我们关闭了终端也不影响进程的正常运行这个进程——->后台运行的进程

4.2 后台运行场景

不会一直占用着自己的窗口后台运行某个命令,不会影响大现在的工作。

4.3 后台程序应用

早期的时候大家都选择使用&符号将进程放入后台,然后在使用jobs、bg、fg等方式查看进程状态,但太麻烦了。也不直观,
推荐使用screen

# ###screen的使用(强烈推荐,生产必用)

#1.安装
[root@oldboy ~]# yum install screen -y

#2.开启一个screen窗口,指定名称
[root@oldboy ~]# screen -S wget_mysql
#3.在screen窗口中执行任务即可

#4.平滑的退出screen,但不会终止screen中的任务。
ctrl+a+d
#注意: 如果使用exit 才算真的关闭screen窗口

#5.查看当前正在运行的screen有哪些

[root@oldboy ~]# screen -list
There is a screen on:
    22058.wget_mysql    (Detached)
1 Socket in /var/run/screen/S-root.

#6.进入正在运行的screen
[root@oldboy ~]# screen -r wget_mysql
[root@oldboy ~]# screen -r 22058

5.优先级

1.什么优先级 优先级指的是进程优先享受资源的权利。 2.为什么要有系统优先级 举个例子: 比如咱们排队很长的的队去检票坐火车时候,如果你有军人证件,那你就可以拥有优先检票的特权,至于没有特权的人员(较低优先级)只能老老实实的进入排队等待状态。

3.系统中如何给进程配置优先级?

在启动进程时,为不同的进程使用不同的调度策略。

nice 值越高: 表示优先级越低,例如+19,该进程容易将CPU 使用量让给其他进程。

nice 值越低: 表示优先级越高,例如-20,该进程更不倾向于让出CPU。

1) 使用top或ps命令查看进程的优先级 | 使用ps查看进程优先级
2) nice指定程序的优先级。语法格式 nice -n 优先级数字 进程名称
3) renice命令修改一个正在运行的进程优先级。语法格式 renice -n 优先级数字 进程pid

6.平均负载

1.什么是平均负载

上面的 0.70,其实上并是单位时间内的 CPU 使用率。

那到底如何理解平均负载: 平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,

PS: 平均负载与 CPU 使用率并没有直接关系。

归纳一下平均负载与CPU

平均负载提供了一个快速查看系统整体性能的手段,反映了整体的负载情况。但只看平均负载本身,我们并不能直接发现,到底是哪里出现了瓶颈。

所以,在理解平均负载时,也要注意:

平均负载高有可能是 CPU 密集型进程导致的;

平均负载高并不一定代表 CPU 使用率高,还有可能是 I/O 更繁忙了;

当发现负载高的时候,你可以使用 mpstat、pidstat 等工具,辅助分析负载的来源

image.png

场景模拟

场景一:CPU 密集型进程

1.首先,我们在第一个终端运行 stress 命令,模拟一个 CPU 使用率 100% 的场景:
[root@m01 ~]# stress --cpu 1 --timeout 600

2.接着,在第二个终端运行 uptime 查看平均负载的变化情况
# 使用watch -d 参数表示高亮显示变化的区域(注意负载会持续升高)
[root@m01 ~]# watch -d uptime
17:27:44 up 2 days,  3:11,  3 users,  load average: 1.10, 0.30, 0.17

3.最后,在第三个终端运行 mpstat 查看 CPU 使用率的变化情况
# -P ALL 表示监控所有 CPU,后面数字 5 表示间隔 5 秒后输出一组数据
[root@m01 ~]# mpstat -P ALL 5
Linux 3.10.0-957.1.3.el7.x86_64 (m01)   2019年04月29日     _x86_64_    (1 CPU)
17时32分03秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
17时32分08秒  all   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00
17时32分08秒    0   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00
#单核CPU所以只有一个all和0

4.从终端二中可以看到,1 分钟的平均负载会慢慢增加到 1.00,而从终端三中还可以看到,正好有一个 CPU 的使用率为 100%,但它的 iowait 只有 0。
这说明,平均负载的升高正是由于 CPU 使用率为 100% 。那么,到底是哪个进程导致了 CPU 使用率为 100% 呢?可以使用 pidstat 来查询
# 间隔 5 秒后输出一组数据

[root@m01 ~]# pidstat -u 5 1
Linux 3.10.0-957.1.3.el7.x86_64 (m01)   2019年04月29日     _x86_64_(1 CPU)
17时33分21秒   UID       PID    %usr %system  %guest    %CPU   CPU  Command
17时33分26秒     0    110019   98.80    0.00    0.00   98.80     0  stress
#从这里可以明显看到,stress 进程的 CPU 使用率为 100%。

场景二:I/0 密集型进程

1.首先还是运行 stress 命令,但这次模拟 I/O 压力,即不停地执行 sync
[root@m01 ~]# stress  --io 1 --timeout 600s

2.然后在第二个终端运行 uptime 查看平均负载的变化情况:
[root@m01 ~]# watch -d uptime
18:43:51 up 2 days,  4:27,  3 users,  load average: 1.12, 0.65, 0.00

3.最后第三个终端运行 mpstat 查看 CPU 使用率的变化情况:
# 显示所有 CPU 的指标,并在间隔 5 秒输出一组数据
[root@m01 ~]# mpstat -P ALL 5
Linux 3.10.0-693.2.2.el7.x86_64 (bgx.com)   2019年05月07日     _x86_64_    (1 CPU)

14时20分07秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
14时20分12秒  all    0.20    0.00   82.45   17.35    0.00    0.00    0.00    0.00    0.00    0.00
14时20分12秒    0    0.20    0.00   82.45   17.35    0.00    0.00    0.00    0.00    0.00    0.00

#会发现cpu的与内核打交道的sys占用非常高

4.那么到底是哪个进程,导致 iowait 这么高呢?我们还是用 pidstat 来查询
# 间隔 5 秒后输出一组数据,-u 表示 CPU 指标
[root@m01 ~]# pidstat -u 5 1
Linux 3.10.0-957.1.3.el7.x86_64 (m01)   2019年04月29日     _x86_64_(1 CPU)
18时29分37秒   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
18时29分42秒     0    127259   32.60    0.20    0.00   67.20   32.80     0  stress
18时29分42秒     0    127261    4.60   28.20    0.00   67.20   32.80     0  stress
18时29分42秒     0    127262    4.20   28.60    0.00   67.20   32.80     0  stress

#可以发现,还是 stress 进程导致的。

场景三:大量进程的场景

当系统中运行进程超出 CPU 运行能力时,就会出现等待 CPU 的进程。
1.首先,我们还是使用 stress,但这次模拟的是 4 个进程
[root@m01 ~]# stress -c 4 --timeout 600

2.由于系统只有 1 个 CPU,明显比 4 个进程要少得多,因而,系统的 CPU 处于严重过载状态
[root@m01 ~]# watch -d uptime
19:11:07 up 2 days,  4:45,  3 users,  load average: 4.65, 2.65, 4.65

3.然后,再运行 pidstat 来看一下进程的情况:
# 间隔 5 秒后输出一组数据
[root@m01 ~]# pidstat -u 5 1
平均时间:   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
平均时间:     0    130290   24.55    0.00    0.00   75.25   24.55     -  stress
平均时间:     0    130291   24.95    0.00    0.00   75.25   24.95     -  stress
平均时间:     0    130292   24.95    0.00    0.00   75.25   24.95     -  stress
平均时间:     0    130293   24.75    0.00    0.00   74.65   24.75     -  stress
可以看出,4 个进程在争抢 1 个 CPU,每个进程等待 CPU 的时间(也就是代码块中的 %wait 列)高达 75%。这些超出 CPU 计算能力的进程,最终导致 CPU 过载。
归纳一下平均负载与CPU
平均负载提供了一个快速查看系统整体性能的手段,反映了整体的负载情况。但只看平均负载本身,我们并不能直接发现,到底是哪里出现了瓶颈。
所以,在理解平均负载时,也要注意:
平均负载高有可能是 CPU 密集型进程导致的;
平均负载高并不一定代表 CPU 使用率高,还有可能是 I/O 更繁忙了;
当发现负载高的时候,你可以使用 mpstat、pidstat 等工具,辅助分析负载的来源