1. 进程基础知识
1.1 程序,进程,守护进程,线程
程序:磁盘上的文件。 进程:运行着的程序。 守护进程:持续运行的进程。 子进程/线程:由进程产生的进程。 生产查进程:ps -aux | ps -ef
1.2 父进程,子进程
当父进程接收到任务调度时,会通过fock派生子进程来处理,那么子进程会继承父进程属性。
- 子进程在处理任务代码时,父进程会进入等待状态中…
- 子进程在处理任务代码后,会执行退出,然后唤醒父进程来回收子进程的资源。
- 如果子进程在处理任务过程中,父进程退出了,子进程没有退出,那么 这些子进程就没有父进程来管理了,孤儿进程。
PS: 每个进程都父进程的PPID,子进程则叫PID。
僵尸进程:一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出。这个子进程就是僵尸进程。任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。
2.监控进程状态
程序在运行后,我们需要了解进程的运行状态。查看进程的状态分为: 静态和动态两种方式
2.1 ps(静态)显示进程状态
1) 示例、ps -aux(详细状态) 常用组合,查看进程 用户、PID、占用cpu百分比、占用内存百分比、状态、执行的命令等
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\内存被正确的利用
对查找的指定列排序:
ps -eo "%C : %p : %z : %a" --sort -vsz
ps -eo "%C : %p : %z : %a" --sort +%cpu
ps -eo "%C : %p : %z : %a" --sort +pid
对查找的树状结构显示:
[root@oldboy ~]# pstree
systemd─┬─NetworkManager───2*[{NetworkManager}]
├─VGAuthService
├─abrt-watch-log
├─abrtd
├─agetty
├─auditd───{audi
2.3 STAT(进程)状态
STAT基本状态 | 描述 | STAT状态+符号 | 描述 |
---|---|---|---|
R | 进程运行 | s | 进程是控制进程, Ss进程的领导者,父进程 |
S | 可中断睡眠 | < | 进程运行在高优先级上,S<优先级较高的进程 |
T | 进程被暂停 | N | 进程运行在低优先级上,SN优先级较低的进程 |
D | 不可中断睡眠 | + | 当前进程运行在前台,R+该表示进程在前台运行 |
Z | 僵尸进程 | l | 进程是多线程的,Sl表示进程是以线程方式运行 |
案例一、PS命令查看进程状态切换
#1.在终端1上运行vim
[root@xuliangwei ~]# vim oldboy
#2.在终端2上运行ps命令查看状态
[root@xuliangwei ~]# ps aux|grep oldboy #S表示睡眠模式,+表示前台运行
root 58118 0.4 0.2 151788 5320 pts/1 S+ 22:11 0:00 oldboy
root 58120 0.0 0.0 112720 996 pts/0 R+ 22:12 0:00 grep --color=auto oldboy
#在终端1上挂起vim命令,按下:ctrl+z
#3.回到终端2再次运行ps命令查看状态
[root@xuliangwei ~]# ps aux|grep oldboy #T表示停止状态
root 58118 0.1 0.2 151788 5320 pts/1 T 22:11 0:00 vim oldboy
root 58125 0.0 0.0 112720 996 pts/0 R+ 22:12 0:00 grep --color=auto oldboy
案例二、PS命令查看不可中断状态进程
#1.使用tar打包文件时,可以通过终端不断查看状态,由S+,R+变为D+
[root@xuliangwei ~]# tar -czf etc.tar.gz /etc/ /usr/ /var/
[root@xuliangwei ~]# ps aux|grep tar|grep -v gre
root 58467 5.5 0.2 127924 5456 pts/1 R+ 22:22 0:04 tar -czf etc.tar.gz /etc/
[root@xuliangwei ~]# ps aux|grep tar|grep -v grep
root 58467 5.5 0.2 127088 4708 pts/1 S+ 22:22 0:03 tar -czf etc.tar.gz /etc/
[root@xuliangwei ~]# ps aux|grep tar|grep -v grep
root 58467 5.6 0.2 127232 4708 pts/1 D+ 22:22 0:03 tar -czf etc.tar.gz /etc/
2.2 top(动态)显示系统状态
(显示系统中各个进程的资源占用状况) 从第七行开始,给出的是各进程(任务)的状态监控。
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.什么是中断
中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求。
2.为什么要有中断呢? "举个生活中的例子"
比如说你订了一份外卖,但是不确定外卖什么时候送到,也没有别的方法了解外卖的进度,但是,配送员送外卖是不等人的,到了你这儿没人取的话,就直接走人了。
所以你只能苦苦等着,时不时去门口看看外卖送到没,而不能干其他事情。
不过呢,如果在订外卖的时候,你就跟配送员约定好,让他送到后给你打个电话,那你就不用苦苦等待了,就可以去忙别的事情,直到电话一响,接电话、取外卖就可以了。
这里的“打电话”,其实就是一个中断。 没接到电话的时候,你可以做其他的事情;只有接到了电话(也就是发生中断),你才要进行另一个动作:取外卖。
这个例子你就可以发现,中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力。节省时间提高效率
3.中断会带来什么问题?
由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行。
如果中断本身要做的事情不多,那么处理起来也不会有太大问题;但如果中断要处理的事情很多,中断服务程序就有可能要运行很长时间。
特别是,中断处理程序在响应中断时,还会临时关闭中断。这就会导致上一次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失。
那么还是以取外卖为例:假如你订了 2 份外卖
一份主食和一份饮料,并且是由 2 个不同的配送员来配送。这次你不用时时等待着,两份外卖都约定了电话取外卖的方式。但是,问题又来了。
当第一份外卖送到时,配送员给你打了个很长的电话,商量发票的处理方式。与此同时,第二个配送员也到了,也想给你打电话。
但是很明显,因为电话占线(也就是关闭了中断响应),第二个配送员的电话是打不通的。所以,第二个配送员很可能试几次后就走掉了(也就是丢失了一次中断)。
4.系统软中断
如果你弄清楚了“取外卖”的模式,那对系统的中断机制就很容易理解了。
事实上,为了解决中断处理程序执行过长和中断丢失的问题,Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:
上半部用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关工作。
下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行。
比如说前面取外卖的例子,上半部就是你接听电话,告诉配送员你已经知道了,其他事儿见面再说,然后电话就可以挂断了;
下半部才是取外卖的动作,以及见面后商量发票处理的动作。
这样,第一个配送员不会占用你太多时间,当第二个配送员过来时,照样能正常打通你的电话。
5.接下来在看一个例子?
除了取外卖,我再举个最常见的网卡接收数据包的例子,让你更好地理解。
网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。
对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),
最后再发送一个软中断信号,通知下半部做进一步的处理。
而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。
所以,这两个阶段你也可以这样理解:
上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行;
而下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行。
Linux软中断与硬中断小结
Linux 中的中断处理程序分为上半部和下半部:
上半部对应硬件中断,用来快速处理中断。
下半部对应软中断,用来异步处理上半部未完成的工作。
Linux 中的软中断包括网络收发、定时、调度、等各种类型,可以通过查看 /proc/softirqs 来观察软中断的运行情况。
PS经常听同事说大量的网络小包会导致性能问题,为什么呢?
因为大量的网络小包会导致频繁的硬中断和软中断?所以大量网络小包传输很慢,但如果将网络包一次传递,是不是会快很多呢?
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 等工具,辅助分析负载的来源
场景模拟
场景一: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 等工具,辅助分析负载的来源