1、什么是进程
-
当一个程序开始执行后,在开始执行到执行完毕退出这段时间内,它在内存中的部分就叫称作一个进程。
-
同一程序可产生多个进程(一对多关系),以允许同时有多位用户运行同一程序,却不会相冲突。
-
一个进程被触发,会占用一定的内存空间,如果内存不够,会触发OOM killer(out-of-memory killer)机制,该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀掉,从而出现系统不稳定的情况。
fork机制:
-
当计算机开机的时候,内核(kernel)只建立了一个systemd(rhel6为init)进程。剩下的所有进程都是systemd进程通过fork机制建立的。
-
父进程产生子进程,使用COW(写时复制)机制,也就是说只有当子进程要修改数据时,父进程才会为子进程clone一块新内存空间。
-
子进程要通过父进程复制自身得到,这就是fork。当进程fork的时候,Linux在内存中开辟出一片新的内存空间给新的进程,并将父进程空间中的内容复制到新的空间中,这时子进程将会被分配到一个唯一的进程ID(PID),此后子进程通过exec的方式加载自己的程序代码。
-
一个进程除了有一个PID之外,还会有一个PPID(parent PID)来存储的父进程PID。如果我们循着PPID不断向上追溯的话,总会发现其源头是systemd进程。所以说,所有的进程也构成一个以systemd为根的树状结构。
进程身份:
对于一个进程而言,也有一个身份,是谁在执行这个可执行文件
#打开一个进程
passwd
#打开一个新终端,查看该进程
ps -elf |grep passwd
2、变量
-
变量分为全局变量和局部变量
-
在linux里,进程之间是有父子关系的,形成一个树形结构
-
全局变量会被子进程继承
-
局部变量不会被子进程继承
例:
#设置一个全局变量
export xx=ls
#设置一个局部变量
zz=kk
#切换一个用户,查看这两个变量是否都能访问
su - tt
echo $xx
-
可以访问
echo $kk
-
不能访问
3、多进程
-
多进程:在系统中同时运行多个进程,但CPU同一时间,只能执行一个任务,将CPU时间分片,多个进程轮流使用。即使多核CPU,一个进程,同一时间,只能被分配到一个CPU上运行
-
多线程:将一个进程中多个不相干的任务,使用多个线程完成,同一时间,多个线程可被分配到多个CPU同时运行,提高执行效率。
-
也就是说,线程是进程的子单位,多线程间可共享进程打开的资源,比如:打开的文件描述符。
4、进程的状态
R |
running,正在被CPU执行或正在等待分配CPU的进程 |
S |
sleeping,可中断的睡眠状态,一般指进程在等待某个事件的发生,而被挂起,比如:服务进程,在没有连接时,就处于sleeping状态,等待有人来连接时再被唤醒,节省资源 |
D |
不可中断的睡眠状态,无法通过kill杀掉它,除非reboot。这种状态一般是因为进程在等待I/O,比如:磁盘I/O,网络I/O等,这时,很可能I/O设备出故障了 |
T |
暂停或停止状态,进程被暂停于内存中,但不会被调度,除非手动启动。 |
Z |
僵尸进程就是已经结束的进程,但是还没有从进程表中删除。僵尸进程太多会导致进程表里面条目满了,进而导致系统崩溃,倒是不占用系统资源。 |
程序运行机制:
-
一个程序运行时,认为内存中只有自己和内核
-
CPU同一时间,只能执行一个指令,所以将CPU时间分片,多进程间轮流使用
-
一个进程在被CPU执行时,如果需要磁盘上的数据,这时,通过系统调用,通知内核,将数据从硬盘读到内存,这个过程称为IO,而进程此时在等待IO,会被内核调度,处于睡眠状态,并且不可中断
这个过程又分两部分:内核先将数据读取到自己的内存中,然后再复制到进程内存中。
-
一个进程耗完CPU时间,会被调度出去,处于睡眠状态,此时可中断
进程分类:
-
CPU-Bound,CPU密集型进程
-
IO-Bound,IO密集型进程,优先级应该高些
5、查看进程
5.1、ps
如果不带任何选项,仅查看当前shell中的进程
所有信息,是通过遍历/proc目录下的进程映射文件获取的
ps命令有两种语法格式:
-
标准格式,带-
-
BSD语法格式,不带-
ps aux |more
-
a,查看所有和终端相关的进程
#TIME 这个进程从触发到现在,共占用了多少CPU时间
-
u,以用户为中心组织进程状态信息显示
#VSZ 虚拟内存集,也就是进程在线性(虚拟)地址空间中实际占用的空间大小
#RSS 常驻内存集,也就是不能被交换到交换分区的内存数据
-
x,查看和终端无关的进程
#TTY以?显示的,表示这个进程和终端无关
#自定义显示信息
ps axo pid,command
#可以查看当前终端进程的父进程,也就是echo $$查看到的,bash进程
ps -l
ps -elf | more
-
e,表示查看所有的进程
-
l,表示以更详细的显示
-
f,显示完整格式的进程信息
显示内容:
-
F,程序标识
#4,说明是通过root用户运行的
#1,表示子程序只进行了fork,而没有实际执行(exec)
#5,apache用户
-
S,进程状态
-
PPID,这个进程的父进程的PID,对于每一个进程而言,都有一个唯一的号码和它的PID
-
STIME,进程启动时间
-
tty,如果为?,表示这是一个内核进程
-
psr,cpu编号,表示运行在哪个cpu上
-
stprio,实时优先级,如果一个进程占用CPU太多,内核会作惩罚,降低其优先级
#以树形结构列出进程间关系
ps -axjf
#查看进程之间的父子关系
pstree
pstree -Aup
-
-A 显示出树形结构
-
-u 显示用户
-
-p 显示PID
#查询进程PID
pidof sshd
5.2、pgrep
#把以htt开头的服务进程的PID显示出来
pgrep -f htt
#精确匹配一个服务名称
pgrep -x httpd
#显示服务的最后启动的进程
pgrep -ln httpd
#显示服务最先启动的进程
pgrep -lo httpd
5.3、top
top
动态显示系统的进程情况,默认每3秒刷新一次
-
时间 #系统当前时间
-
up #系统运行时间
-
load average #CPU在1分钟、5分钟、15分钟内的平均负载,表示单位时间内队列中正在等待CPU调度的进程数的平均值。可用uptime命令查看
-
tasks #多少个任务
-
cpu #cpu使用情况
-
mem #内存使用情况
-
swap #虚拟内存使用情况
-
PID 进程的PID
-
USER 用户
-
PR 优先级
-
NI PR+NI才是这个进程真正的优先级
-
VIRT 虚拟内存
-
RES 实际内存
-
SHR 共享内存,两个进程间会共享内存页
-
S 进程状态
-
%CPU CPU百分比
-
%MEM 内存的百分比
-
TIME+ CPU的占用时间
-
COMAND 进程文件
命令:
-
?帮助
-
P 按CPU的百分比来排序
-
M 按内存的百分比来排序
-
N 以PID来排序
-
q 退出
#每2秒刷新一次,共刷新3次
top -d 2 -n 3
#查找固定进程的资源使用情况
top -d 2 -n 3 -p PID
5.4、vmstat
查看内存状态的工具
#每一秒刷新一次,刷新3次
vmstat 1 3
显示内容解释:
-
procs
−r,等待运行的进程的个数
−b,处于不可中断睡眠态的进程个数,被阻塞的队列的长度
-
memory
−swpd,交换内存的使用总量
−free,空闲物理内存总量
−buffer,用于存放要写入到磁盘的数据,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。可使用sync命令,手动将数据同步到磁盘。
−cache,从磁盘读出存放到内存中,待今后使用的数据
-
swap
−si,数据进入swap的速率,单位kb/s
−so,数据离开swap的速率
-
io
−bi,从块设备读取数据的速率
−bo,保存数据至块设备的速率
-
system
−in,中断速率
−cs,上下文切换速率(也称为进程切换)
-
cpu
−us,用户空间所使用的CPU时间比率
−sy,内核空间所使用的时间比率
−id,空闲比率
−wa,等待IO完成所消耗的时间比率
−st,被偷走的时间比率
#查看内存的统计信息
vmstat -s
#查看内存空间使用情况
free -m
5.5、lsof
查看系统打开的文件数
#查看80端口被谁占用
lsof -i:80
5.6、pidof
#查看ping进程的PID
pidof ping
6、进程的中断
进程管理进程,kill也是一个进程,发出一个信号对进程进行操作
6.1、kill
-
杀掉进程,注意:根进程(systemd或init)是杀不掉的
-
向指定的进程或进程组发送信号,对进程进行控制
-
确定进程是否还在
kill -信号 PID
-
只会杀掉指定的单个进程
-
不带信号选项,默认用15号信号
6.2、killall或pkill
#将名称匹配的进程全部杀掉
killall -信号 进程名字
#将名称匹配的进程全部杀掉
pkill -信号 进程名字
6.3、信号
#查看所有信号
kill -l
信号 |
解释 |
0 |
用来检测进程是否存在 如:killall -0 httpd,如果什么输出都没有,表示有这个进程,否则,会输出告诉你没有这个进程。 也可用echo $?来检测killall -0 httpd命令是否执行成功 |
1 |
表示挂起,让这个进程去重新加载配置文件,一般用于服务,用短称HUP代替1也可以 |
2 |
表示键盘中断,向处于前台的进程发送一个终止运行的信号,如:ctrl+c 例:ping 8.8.8.8,这时,给这个进程发送一个2号信号,该进程就被终止了 |
3 |
表示键盘退出,和信号2的作用类似,但在杀死进程的同时,又将进程启动了。如:ctrl+\ 例:ping 8.8.8.8,这时,给这个进程发送一个3号信号,就掉一个包 |
9 |
表示中断,无法拦截,不能正常结束的进程,可用信号9强制杀掉。 killall -9 httpd 把httpd服务全杀掉,用-9杀掉的进程,比较难再启动,相当于直接把电源拔掉 |
15 |
表示终止,正常终止进程,相当于正常关机,如果kill命令不带任何选项,默认就是这个信号 |
18 |
继续,让暂停的进程继续运行,如:fg、bg命令 |
19 |
暂停,将一个程序暂停运行,如:ctrl+z,将一个进程放到后台,并暂停运行 |
7、控制进程作业
比如:ping,当前终端就不能做其它操作了,这是因为当触发一个子进程的时候,父进程进入休眠状态,直到子进程退出
#查看ping的父进程是2276
ps -elf |grep ping
#查看父进程的状态
ps -elf |grep 2276
-
只有作业控制,才可以让终端可以同时进行多个操作,比如:ping 10.0.0.1 &
-
前台进程:和终端相关,通过终端启动的进程
-
守护进程:和终端无关,一般通过系统引导过程中启动的进程
7.1、&
加在一个命令的最后,可以把这个命令放到后台执行
#将ping命令放到后台运行
ping 1.1.1.1 &
7.2、ctrl + z
可以将一个正在前台执行的命令放到后台,并且处于暂停状态。
ping 1.1.1.1
ctrl+z
7.3、jobs
查看当前有多少在后台运行的命令
#显示所有任务的PID
#jobs的状态可以是running, stopped, terminated
#但是如果任务被终止了(kill),shell 从当前的shell环境已知的列表中删除任务的进程标识
jobs -l
7.4、fg
将后台中的命令调至前台继续运行。如果后台中有多个命令,可以用fg %jobnumber(是命令编号,不是进程号)将选中的命令调出。
#将后台运行的命令编号为1的进程调到前台执行
fg %1
7.5、bg
将一个在后台暂停的命令,变成在后台继续执行。
#通过job id控制后台的进程继续执行
bg %2
7.6、kill
方法1:通过jobs命令查看job号(假设为num),然后执行kill %num
方法2:通过ps命令查看job的进程号(PID,假设为pid),然后执行kill pid
前台进程的终止:Ctrl+c
7.7、nohup
-
实现让一个进程始终保持在后台运行,即使关闭当前的终端也没关系
-
可以让一个进程的父进程变成1,和终端无关,脱机运行,除非关机
#使用nohup,执行ping
#然后关掉当前终端,打开一个新终端
nohup ping 10.0.0.1 &
ps -elf |grep ping
-
可以看到这个进程还在运行,并且终端变成?,父进程PID为1