进程介绍
程序:存放代码的文件=》静态
进程:程序运行的过程=》动态
-
描述方式1:程序的运行过程
-
描述方式2:操作系统控制着硬件去运行程序的过程
-
PS:进程是操作系统最核心的概念
-
并发:多个任务看起来是同时运行的即可
-
并行:多个任务是真正的同时运行 只有多核才能实现并行
-
强调:cpu是运行代码,不是做io的
-
线程:进程内代码的执行过程 线程才是cpu上的执行单位 一个进程内至少有一个线程
-
一个进程的多个线程共享该进程的内存资源,不同进程的多个线程的内存资源互相隔离
提交任务的方式:
-
同步:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行
-
异步:提交完一个任务之后,不在原地等待,结果直接执行下一行代码,会导致任务是并发执行的
注意:
-
1.当程序运行为进程后,系统会为该进程分配内存,以及运行的身份和权限。
-
2.在进程运行的过程中,服务器上回有各种状态来表示当前进程的指标信息。
同一程序可能对应多个进程
-
父进程:程序运行时对产生的第一个进程
-
子进程:有父进程衍生fork()出来的进程
-
注意:如果父进程终止,子进程也会随之被终止
进程之间的状态(R、S、D、T、Z、X)
-
R- -可执行状态(运行状态)
-
只有运行状态的进程才有可能在CPU上运行,注意的是可能,并不意味着进程一定在运行中。同一时刻可能有多个进程处在可执行状态,这些进程的PCD (进程控制块) 被放入对应CPU 的可执行队列中。然后进程调度器从各个可执行队列中分别选择一个进程在CPU 上运行。
另外如果计算机只有一个处理器, 那么一次最多只有一个进程处于这种状态。
-
-
S- -可中断睡眠状态(sleeping)
-
处在这个状态意味着进程在等待事件完成。这些进程的PCB (task struct结构) 被放入对应时间的等待队列中。然后等待的事件发生时, 对应的进程将被唤醒。
-
-
D- -不可中断睡眠(disk sleep)
-
在这个状态的进程通常会等待I0 的结束。
这个状态与sleeping状态相似, 处于睡眠状态, 但是此刻进程是不可中断的, 意思是不响应异步信号。另外你会发现处在D状态的进程kill - 9竟然也杀不死。这就相当于我们怎么也叫不醒一个装睡的人。
-
-
T- -暂停状态
-
给进程发送一个sIGsm0P 信号, 进程就会响应信号进入m状态, 除非该进程正处在D状态。再通过发送sIGc0Nm 信号让进程继续运行。
kill - sIGsm0P
kill - sIGc0Nm
-
-
Z- -僵尸状态
-
僵死状态是一个比较特殊的状态。进程在退出的过程中, 处于mAsK DEAD状态。
在这个退出过程中, 进程占有的所有资源将被回收, 除了task struct结构 (以及少数资源) 以外。于是进程就只剩下task struct这么个空壳, 故称为僵尸。
u- - 死亡状态或退出状态 (dead)
死亡状态是内核运行 kernel /exit.c 里的 do exit( ) 函数返回的状态。这个状态只是一个返回状态, 你不会在任务列表里看到这个状态
-
进程状态切换
任务的三种运行状态
-
就绪状态
-
当进程已分配到除CPU 以外的所有必要的资源, 只要获得处理机便可立即执行, 这时的进程状态称为就绪状态。
-
-
运行态(执行状态)Runing
-
当进程已获得处理机, 其程序正在处理机上执行, 此时的进程状态称为执行状态
-
-
阻塞态((Blocked)
-
正在执行的进程, 由于等待某个事件发生而无法执行时, 便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种, 例如, 等待I/0完成、申请缓冲区不能满足、等待信件( 信号)等。
-
-
就绪态=》运行态
-
就绪态抢到CPU资源时转换为运行态
-
-
运行态=》就绪态
-
运行态在失去CPU资源时进入就绪态
-
-
运行态=》阻塞态
-
运行态在进行IO操作时进入阻塞态
-
-
阻塞态=》就绪态
-
阻塞态在读写完IO后转换为就绪态
-
查看进程
ps aux, 查看进程用户、PID、占用百分比、占用内存百分比、状态、执行的命令等。
[root@localhost ~]# ps aux
a:显示一个终端的所有进程
u:选择有效的用户ID或者是用户名
x:显示没有控制终端的进程,同时显示各个命令的具体路径
示例
[root@instance-lpbn3wlc ~]# ps aux |head -5
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 95140 11120 ? Ss Nov01 0:22 /usr/lib/systemd/systemd --system --deserialize 20
root 2 0.0 0.0 0 0 ? S Nov01 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< Nov01 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< Nov01 0:00 [rcu_par_gp]
-
在多任务处理操作系统中,每个CPU(或核心)在一个时间点上只能处理一个进程。
-
在进程运行时,它对 CPU 时间和资源分配的要求会不断变化,从而为进程分配一个状态,它随着环境要求而改变
查看结果显示
USER: //启动程序的用户
PID: //进程ID
%CPU: //CPU占用率
%MEM: //内存占用率
VSZ: //占用虚拟内存,单位:kb(killobytes)
Vsx是指已分配的线性空间大小, 这个大小通常并不等于程序实际用到的内存大小, 产生这
个的可能性很多
比如内存映射, 共享的动态库, 或者向系统申请了更多的堆, 都会扩展线性空间大小。
RSS: //占用实际内存,单位:kb(killobytes)
Rsx是Resident set siye, 常驻内存大小, 即进程实际占用的物理内存大小
?
TTY: //进程运行的终端
?: #内核运行的终端
tty1: #机器运行的终端
pts/0: #远程连接的终端
?
STAT: //进程状态 man ps (/STATE)
D: #不可中断睡眠, 即在睡眠的过程中不可以接收信号唤醒=》执行的I0操作得不到硬件设备的响应
R: #正在运行的状态
S: #可中断睡眠 sleep, 即在睡眠的过程中可以接收信号唤醒=》执行的I0操作可以得到硬件设备的响应
T: #停止的进程
W: #进入内存交换(从内核2.6开始无效)
X: #死掉的进程(几乎看不见,因为死了就立即回收了)
Z: #僵尸进程
<: #优先级高的进程
N: #优先级较低的进程
L: #有些页被锁进内存
s: #父进程(在它之下有子进程开启着)
l: #小写字母l , 代表以线程的方式运行, 即多线程
|: #管道符号代表多进程
+: #该进程运行在前台
START: //进程的启动时间
TIME: //进程占用CPU的总时间
COMMAND: //进程文件,进程名
[]: #内核态的进程
没[]: #用户态的进程
linux进程有两种睡眠状态
# 1、Interruptible sleep (可中断睡眠, 在ps命令中显示" s" )
处在这种睡眠状态的进程是可以通过给它发送signal来唤醒的, 比如发HUP 信号给nginx的master进程可以让nginx重新加载配置文件而不需要重新启动nginx进程;
# 2、Uninterruptible sleep (不可中断睡眠, 在ps命令中显示"D" )
处在这种状态的进程不接受外来的任何signal, 这也是为什么之前我无法用kill 杀掉这些处于D状态的进程, 无论是"kill " 、"kill - 9"、"kill - 15" 还是按 ctrl +c 、ctrl +x 都无济于, 因为它们压根儿就不受这些信号的支配。
?
# 解释
进程为什么会被置于D状态呢? 处于uninterruptible sleep状态的进程通常是在等待I0 , 比如磁盘I0 , 网络I0 , 其他外设I0 , 如果进程正在等待的I0 在较长的时间内都没有响应, 那么就很会不幸地被ps 看到了, 同时也就意味着很有可能有I0 出了问题, 可能是外设本身出了故障, 也可能是比如NFS挂载的远程文件系统已经不可访问了。
?
正是因为得不到I0 的响应, 进程才进入了uninterruptible sleep状态, 所以要想使进程从uninterruptible sleep状态恢复, 就得使进程等待的I0 恢复, 比如如果是因为从远程挂载的NPs 卷不可访问导致进程进入uninterruptible sleep状态的, 那么可以通过恢复该NPs 卷的连接来使进程的I0 请求得到满足, 除此之外, 要想干掉处在D状态进程就只能重启整个工inux 系统了 (恐怖的D状
态) 。
?
看到有人说如果要想杀掉D状态的进程, 通常可以去杀掉它的父进程 (通常是shell , 我理解的这种情况是在shell 下直接运行的该进程, 之后该进 程转入了D状态) , 于是我就照做了, 之后就出现了上面的状态: 他们的父进程被杀掉了, 但是他们的父进程PID 都变成了1 , 也就是init进程, 这下可如何是好? 此时我这些D状态的进程已经影响到其他一些进程的运行, 而已经无法访问的NPs 卷又在段时间内无法恢复, 那么, 只好重新启动了。
?
# 强调
D与x状态的进程都无法用kill - 9杀死
示例1:PS命令查看前台进程转换到停止
#在终端上运行vim
[root@zls ~]# vim zls.txt
?
#查看vim运行的状态,S:睡眠状态 +:在前台运行
[root@zls ~]# ps aux|grep [v]im
root 1306 0.0 0.2 151664 5180 pts/0 S+ 13:00 0:00 vim zls.txt
?
#执行ctrl + z,将进程放置后台
[1]+ 已停止 vim zls.txt
?
#进程状态变成了T,暂停或被追踪的状态
[root@zls ~]# ps aux|grep [v]im
root 1306 0.0 0.2 151664 5180 pts/0 T 13:00 0:00 vim zls.txt
案例二:PS命令查看不可中断状态
# 1.在窗口1执行命令
[root@egon ~]# tar cvzf egon.tar.gz /etc/ /usr/ /var/ /usr/
# 2.在窗口2查看tar的状态:S+、R+、D
[root@egon ~]# while true;do ps aux |grep [t]ar;sleep 0.3;clear;done
?
案列三:查看进程优先级(nice好心值)
#nice 好心值
#好心值越低,优先级越高,好心值越高,优先级越低。范围-20~ +19[root@instance-lpbn3wlc ~]# nice -n -20 sleep 3000 &[1] 130188
[root@instance-lpbn3wlc ~]# nice -n 19 sleep 3000 &
[2] 130201
[root@instance-lpbn3wlc ~]# ps aux | grep sleep
root 130188 0.0 0.0 7280 772 pts/1 S< 20:34 0:00 sleep 3000
root 130201 0.0 0.0 7280 836 pts/1 SN 20:34 0:00 sleep 3000
root 130239 0.0 0.0 12108 1064 pts/1 S+ 20:35 0:00 grep --color=auto sleep
[root@instance-lpbn3wlc ~]# nice -n 16 sleep 9000 &
[3] 130303
[root@instance-lpbn3wlc ~]# ps aux | grep [s]leep
root 130188 0.0 0.0 7280 772 pts/1 S< 20:34 0:00 sleep 3000
root 130201 0.0 0.0 7280 836 pts/1 SN 20:34 0:00 sleep 3000
root 130303 0.0 0.0 7280 788 pts/1 SN 20:38 0:00 sleep 9000
?
案列四:模拟开启多线程
[root@instance-lpbn3wlc ~]# python aaa.py
代码如下:
from threading import Thread
import time
import os
?
def task():
time.sleep(100)
?
if __name__ == "__main__":
print(os.getpid())
for i in range(10):
t=Thread(target=task)
t.start()
查看进程树:以树状结构显示进程关系。
-
pstree UID:显示指定的进程及子进程。
-
-a:显示每个程序的完整指令,包含路径,参数或是常驻服务的标示。
[root@instance-lpbn3wlc ~]# yum install -y psmisc 最小化安装可能没有pstree,需要安装psmisc
[root@egon ~]# rpm -qf `which pstree`
psmisc-22.20-16.el7.x86_64
[root@oldboy ~]# pstree
systemd─┬─VGAuthService
├─auditd───{auditd}
├─chronyd
├─crond
├─dbus-daemon
├─irqbalance
├─login───bash
├─master─┬─pickup
│ └─qmgr
├─ping
├─polkitd───6*[{polkitd}]
├─rsyslogd───2*[{rsyslogd}]
├─sshd───bash
├─sshd───bash───pstree
├─sshd
├─systemd-journal
├─systemd-logind
├─systemd-udevd
├─tuned───4*[{tuned}]
└─vmtoolsd
[ rootaegon ~ ]# pstree 104239
查看ppid
ps命令使用方法:
#对进程的CPU进行排序展示
[root@zls ~]# ps aux --sort %cpu |less
?
#对进程的占用物理内存排序
[root@zls ~]# ps aux --sort rss |less
?
#排序,是在记不住,那就自己排序
[root@zls ~]# ps aux|sort -k3 -n
?
#自定义显示字段
[root@zls ~]# ps axo user,pid,ppid,%mem,command |grep sshd
root 869 1 0.2 /usr/sbin/sshd -D
root 1194 869 0.2 sshd: root@pts/0
root 1307 869 0.2 sshd: root@pts/1
root 1574 869 0.2 sshd: root@pts/2
?
#显示进程的子进程
[root@zls ~]# yum install nginx -y
[root@zls ~]# systemctl start nginx
[root@zls ~]# ps auxf|grep [n]ginx
root 2033 0.0 0.1 125096 2112 ? Ss 13:29 0:00 nginx: master process /usr/sbin/nginx
nginx 2034 0.0 0.1 125484 3148 ? S 13:29 0:00 \_ nginx: worker process
?
#查看指定进程PID
[root@zls ~]# ps aux|grep sshd
root 1157 0.0 0.1 105996 3604 ? Ss Feb27 0:00 /usr/sbin/sshd -D
[root@zls ~]# cat /run/sshd.pid
1157
?
#pgrep常用参数, -l -a
[root@zls ~]# pgrep sshd
869
1194
1307
1574
[root@zls ~]# pgrep -l sshd
869 sshd
1194 sshd
1307 sshd
1574 sshd
[root@zls ~]# pgrep -l -a sshd
869 /usr/sbin/sshd -D
1194 sshd: root@pts/