Linux 进程管理
基础知识
进程
内核的功能和作用:文件系统管理、网络管理、进程管理、内存管理等,属于linux最基础的功能
进程:process,正在运行中的程序的一个副本。允许有多个进程同时执行。
#操作系统负责分配cpu运行进程的顺序和时间
#副本:把磁盘上的指定文件加载到内存进行运行 运行多次就会有多个副本
#多实例:一个程序生成多个副本,每个副本在内存中独立运行
#进程是资源使用的分配单位,进程存在声明周期
#PID:进程的唯一标号
进程创建过程: #进程的父子关系:写实复制
1. 操作系统启动的时候有个总进程(系统的第一个进程):centos6--init centos7及以上--systemd
2. 后续的所有进程都是总进程生成的,一次推类,构成一个树状结构,c语言使用fork()函数创建子进程
#父进程创建子进程的过程:
父进程在内存中占有一片空间,创建子进程的时候,此时子进程用的内存空间是父进程那一块空间。当子进程产生数据更新以后,就会复制父进程的空间来作为自己独立的空间。
线程
线程:进程是系统资源分配的单位。进程在处理数据的时候,通过线程来完成任务。
#进程相当于一个组织,线程就相当于这个组织里面干活的员工。进程和线程是包含关系,多个线程共享进程的空间。
#线程在运行的时候的执行顺序由操作系统决定
#一颗CPU同时只能执行一件事,他将时间切成很小的时间片,不同的时间片做不同的任务,所以就感觉在同时做多件事情(实际上是轮流执行程序的)。
使用 pstree -p 可以看到系统中的进程和线程。#只有一个线程后面就不显示了(后面没有花括号)。
协程
协程:一个协程就相当于一个函数。
进程、线程、协程的区别:
1.线程是程序执行的最小单位,进程是操作系统分配资源的最小单位;
2.一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线
3.进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间
进程的结构
-
任务列表
-
PCB
任务列表概念
任务列表:操作系统允许运行多个进程,进程之间构成了一个进程列表(任务列表),所有进程都放在里面的。
PCB概念
PCB:存放一个具体进程的全部信息(包括进程编号、状态、优先级等),因为系统有多个进程,所以就存在多个PCB,每个PCB之间通过指针变量关联
页(Page)
页:进程内存资源的分配的最小单位,类似于文件系统的block,页的默认大小也是4k
虚拟地址和物理地址
-
虚拟地址
-
物理地址
虚拟地址
虚拟地址:存放相对地址,位置是变化的。不是固定的。
应用程序看到的是虚拟地址
物理地址
物理地址:具体的一个固定地址
MMU
MMU:内存管理单元(cpu中的硬件芯片),把虚拟地址转换成物理地址。
进程访问某个数据的时候,先把请求发送给操作系统,操作系统再交给cpu,cpu计算为物理地址,然后才能得到真正的数据。
tlb
tlb:缓存虚拟地址和物理地址的区域
内存的分配空间
-
用户空间:进程虚拟内存空间
-
内核空间:操作系统使用的
每个进程都包括5种不同的数据段
-
代码段
-
数据段
-
BSS段
-
栈
-
堆
代码段:存放可执行文件的操作指令
数据段:存放初始化了的全局变量
BSS段:存放未初始化的全局变量 #Block Started by Symbol”的缩写,意为“以符号开始的块
栈:存放临时变量(比如函数里面使用的变量) #先进后出 队列就是先进先出
堆:存放数组、对象
进程使用内存问题
-
内存泄漏
-
内存溢出
内存泄露: Memory Leak,分配的空间不释放,一直占用着
内存溢出:Memory Overflow,程序申请的空间不够用。
内存不足:OOM,内存不够用(java中的一种提示)
进程运行的状态
-
创建
-
就绪:
-
执行
-
终止
-
阻塞
使用 ps aux 可以看到进程的状态
进程更多的状态:
运行态:running #正在运行
就绪态:ready
睡眠态:进程不干活了,可中断:interruptable,不可中断(不能人为打断):uninterruptable
停止态:stopped,进程处于暂停的状态
僵死态:zombie,僵尸态,结束进程,父进程结束前,子进程不关闭,杀死父进程可以关闭僵死
态的子进程(这种进程不占用空间)
#结束僵尸态的方法:把它的父进程杀死就没了或者恢复父进程
LRU 算法
LRU:Least Recently Used 近期最少使用算法(喜新厌旧),用来实现内存的充分利用
IPC 进程之间的通信
IPC: Inter Process Communication
通信方法:
-
同主机
-
跨主机
同一主机上:
-
管道
-
套接字
-
文件映射
-
共享内存
-
信号
管道:cmd1 | cmd2 (管道符的两边就开启了两个进程),单工通信 # | 这属于匿名管道
#命名管道:创建一个管道(pipe)文件,用来实现两个进程之间的通信。 A--->管道文件--->B
#创建管道文件的命令:mkfifo(fifo:先进先出)
#格式: mkfifo pipe_name
套接字:进程之间双向通讯
#查看套接字的方法:find / -type s -ls
文件映射:文件的数据映射到内存的一块空间中,多个进程共享这块内存空间
共享内存:直接在内存中分配一块空间,这块空间大家都能使用。
信号:trap -l 可以查看。发个信号进程收到以后就会按照指定的功能来进行操作。
跨主机通信:
socket:socket就是ip加上端口号。ip地址确定了设备在网络中的位置。端口号确定了设备上了具体应用程序。(使用tcp、udp协议都会分配要给与众不同的独有端口)
范例
范例:利用管道文件实现 IPC
mkfifo /data/test.fifo #创建一个管道文件
ll /data/test.fifo #使用ll查看管道的信息,发现它的大小是0字节,
cat > /data/test.fifo #输入123456
#在管道文件里面写入数据以后,不会自动退出,且此时文件的大小依然是0,以为这个管道文件是在内存里面的,不是在磁盘里面。
#在另一个终端可以从文件中读取数据
cat /data/test.fifo #会读取到123456
进程的优先级
CentOS优先级:
系统优先级:0-139, 数字越小,优先级越高
实时优先级(realtime): 99-0 值最大优先级最高
nice值(nice优先级):-20到19,对应系统优先级100-139 #一般进程启动以后,优先级使用nice优先级的0
top工具显示的优先级是0-39,对应系统优先级的100-139
设置和调整进程优先级
静态优先级:100-139
进程默认启动时的nice值为0,优先级为120
只有根用户才能降低nice值(提高优先性)
nice命令
以指定的优先级来启动进程
nice -n number command
例如:#nice -n -10 ping 127.0.0.1 #调整平命令的优先级为-10
进程分类
操作系统分类:
-
协作式多任务:
-
抢占式多任务:
协作式多任务:一个任务得到cpu后,只有它主动放弃cpu,其他进程才能使用
抢占式多任务:CPU的控制权由操作系统控制(由操作系统分配cpu资源)
进程类型
-
守护进程
-
前台进程
守护进程:daemon,计算机启动以后就自动运行,就和终端没关系了。
前台进程:跟终端相关,通过终端启动的进程
#二者可以进行转换
进程管理工具
pstree工具:
可以显示进程之间的父子关系
#格式:
pstree [选项] [pid|user] #可以查看指定的进程信息,也可以查看所有的进程关系
#选项:
-p:显示pid
-T:不显示线程
ps工具:
作用:实现进程信息的查看,默认显示当前终端中的进程(显示的是当前瞬间的状态)
#ps默认显示的是当前终端中用户运行的进程列表。
Linux系统各进程的相关信息均保存在/proc/PID目录下的各文件中
#格式:
ps [选项]
#三种选项风格:
UNIX选项 如: -A -e #单个字母
GNU选项 如: --help #完整单词
BSD选项 如: a #只需要一个字母
#常用选项:
a 选项包括所有终端中的进程
u 显示每个进程是以谁的身份运行等信息
x 显示和终端有关或无关的进程(和终端无端:随计算机启动就启动了)
o 属性… 显示指定的属性列 pid、cmd、%cpu、%mem
-e 显示所有进程,相当于-A
-f 显示完整格式程序信息
-p pid 显示指pid的进程
-t ttylist 指定tty,相当于 t
ps命令的输出信息:
C : ps -ef 显示列 C 表示cpu利用率
VSZ: 操作系统承诺给进程的空间(虚拟内存占用空间)
RSS: 操作系统实际给进程的空间(实际内存占用空间)
TTY:所在的终端,如果是?号表示和终端无关
STAT:进程状态
R:running #正在运行中的
S: interruptable sleeping #可中断的睡眠
D: uninterruptable sleeping #不可中断睡觉
T: stopped #停止
Z: zombie #僵尸
+: 前台进程
l: 多线程进程
L:内存分页并带锁
N:低优先级进程
<: 高优先级进程
s: session leader,会话(子进程)发起者
I:Idle kernel thread,CentOS 8 新特性
ni: nice优先级,nice值 #范围-20 --- 19 对应:100-139
pri: priority 系统优先级数字 #数字越大,优先级越高
rtprio: 实时优先级 #对应系统0-99
psr: processor 显示进程和cpu之间的绑定关系 #进程在那颗cpu上运行
范例
#ps -ef #unix风格
#ps aux #bsd风格
这个风格的选项显示的信息没有aux显示的要全
##查看进程的特定属性
例如:#ps axo pid,cmd,%mem,%cpu
#找到未知进程的执行程序文件路径
#ps命令显示的只是pid和程序的名称,没有显示程序的文件路径
ls -l /proc/1272/exe #1272表示进程的pid exe是一个软连接,指向程序的路径
#范例:查看优先级和CPU绑定关系
#ps axo pid,cmd,psr |grep 进程名
prtstat工具:
查看进程的信息
#格式
prtstat [选项] pid
例如:#prtstat 1026
[root@Centos8 ~]# prtstat 1026
Process: sshd State: S (sleeping)
CPU#: 1 TTY: 0:0 Threads: 1
Process, Group and Session IDs
Process ID: 1026 Parent ID: 1
Group ID: 1026 Session ID: 1026
T Group ID: -1
Page Faults
This Process (minor major): 718 8
Child Processes (minor major): 80458 11
CPU Times
This Process (user system guest blkio): 0.05 0.06 0.00 0.00
Child processes (user system guest): 93.69 11.96 0.00
Memory
Vsize: 94 MB
RSS: 7856 kB RSS Limit: 18446744073709 MB
Code Start: 0x56188adb7000 Code Stop: 0x56188ae83f38
Stack Start: 0x7fffde7c3120
Stack Pointer (ESP): 0 Inst Pointer (EIP): 0
Scheduling
Policy: normal
Nice: 0 RT Priority: 0 (non RT)
查看某个进程的方法
- ps 选项 | grep 'pattern' #查找某个进程
- /sbin/pidof 按确切的程序名称查看pid
- pgrep工具
pgrep
专门的进程过滤工具
命令格式:
pgrep [options] pattern
# 选项:
-u uid: effective user,进程所有者
-U uid: real user,真正发起运行命令者
-t terminal: 与指定终端相关的进程
-l: 指定进程名 #根据进程名显示进程信息
-a: 显示完整格式的进程名
-P pid: 显示指定进程的子进程
pidof
知道程序名,用来获取进程pid。
格式:pidof process _name
#选项:
-x: 查找脚本的进程id #脚本必须shebang机制开头,以bash的方式来运行找不到,需要加权限来运行才找得到
uptime
系统负载信息查询
#和w命令、top命令最上面显示的信息也是一样的。
#显示信息
当前时间
系统已启动的时间
当前上线人数
系统平均负载(1、5、15分钟的平均负载,一般不会超过1,超过5时建议警报)
实时进程的查看:
-
htop工具
-
top工具
top工具
动态实时查看进程信息
#选项:
-d # 指定刷新时间间隔,默认为3秒
-b 全部显示所有进程
-n # 刷新多少次后退出
-H 线程模式
#top命令显示的信息
us:用户空间
sy:内核空间
ni:调整nice时间
id:空闲
wa:等待IO时间
hi:硬中断
si:软中断(模式切换)
st:虚拟机偷走的时间
htop工具
top工具的增强版。
#选项;
-d #: 指定延迟时间;
-u UserName: 仅显示指定用户的进程
-s COLUME: 以指定字段进行排序
#子命令
s:跟踪选定进程的系统调用
l:显示选定进程打开的文件列表
a:将选定的进程绑定至某指定CPU核心
t:显示进程树
CPU相关信息显示:mpstat工具
来源:sysstat包
显示信息说明:
CPU:
%usr:用户空间占用时间
%nice:nice优先级
%sys:系统内核占用时间
%iowait:io等待
%irq:中断
%soft:软中断
%steal:被虚拟机运行占用的时间
%guest:和虚拟化有关的
%gnice:虚拟机调整优先级
%idle:空闲的时间
PID(进程id)
USER(进程发起者)
PR(top里面的优先级)
NI(nice优先级)
VIRT(虚拟内存空间)
RES(实际内存占用空间)
SHR(共享内存占用空间)
S(进程状态)
%CPU(cpu利用率)
%MEM(内存)
TIME+(总的运行时间)
COMMAND(对应的命令)
内存相关信息查看
free 可以显示内存空间使用状态
选项:
-b 以字节为单位
-m 以MB为单位
-g 以GB为单位
-h 易读格式
-o 不显示-/+buffers/cache行
-t 显示RAM + swap的总和
-s n 刷新间隔为n秒
-c n 刷新n次后即退出
缓存的清理方法
向/proc/sys/vm/drop_caches中写入相应的修改值,会清理缓存
执行echo
1、2、3 至 /proc/sys/vm/drop_caches, 达到不同的清理目的
查看进程打开文件 lsof
lsof:list open files,列出正在打开的文件。
#选项:
-a:列出打开文件存在的进程
-c<进程名>:列出指定进程所打开的文件
-g:列出GID号进程详情
-d<文件号>:列出占用该文件号的进程
+d<目录>:列出目录下被打开的文件
+D<目录>:递归列出目录下被打开的文件
-n<目录>:列出使用NFS的文件
-i<条件>:列出符合条件的进程(4、6、协议、:端口、 @ip )
-p<进程号>:列出指定进程号所打开的文件
-u:列出UID号进程详情
-h:显示帮助信息
-v:显示版本信息。
-n: 不反向解析网络名字
范例
查看某个端口是那个进程在使用
#查看所有正在打开的文件:
lsof
#找回被误删除的文件 前提是这个文件有人在访问
1. lsof | grep delete #过滤出被删除的文件,找到正在访问这个文件的进程编号
2. ll /proc/pid/fd #fd:文件描述符
3. cat /proc/pid/fd/文件描述符 > 导出为新文件
信号的管理
kill工具
用来向进程发送控制信号,以实现对进程管理,每个信号对应一个数字,信号名称以
SIG开头(可省略),不区分大小写
#显示当前可用的信号:
trap -l
kill -l
#常用信号:
1) SIGHUP 无须关闭进程而重新加载配置文件
2) SIGINT 中止正在运行的进程;相当于Ctrl+c
3) SIGQUIT 相当于ctrl+\ #退出进程
9) SIGKILL 强行关闭某个进程,可能会导致数据丢失(相当于按电源关机)
15) SIGTERM 正常关闭某个进程,默认信号
18) SIGCONT 继续运行
19) SIGSTOP 后台休眠
#信号的描述方法
数字法:1, 2, 9
全称:SIGHUP,sighup
简称 去掉开头的SIG,HUP,hup
#向进程发送信号
通过pid的方式:
kill [-s sigspec | -n signum | -sigspec] pid
#-s sigspec:指定完整的信号名
#-n signum:信号的数字表示法
#-sigspec:信号的简写方法
#根据程序名发送信号
killall 程序名称
#0信号
信号为0,没有发送任何信号,仅仅检查进程是否正常工作。
格式: killall -0 程序名
例如:
[root@centos8 ~]#killall -0 ping
[root@centos8 ~]#echo $? ---> 0
作业管理
-
前台运行管理
-
后台运行管理
前台运行管理:
前台:依赖一个终端,在某个终端运行,启动以后就占用这个终端,在这个终端里面就不能做其他的操作了
例如: ping 127.0.0.1
后台运行管理
后代:不占用终端资源,在进程执行的时候加一个&符号
例如:ping 127.0.0.1 &
前后台运行的切换
默认大多数命令是前台执行,前后台是可以切换的。
CTRL+C就是给前台执行的程序发送终止信号,快捷键支队前台执行的生效。对后台执行的程序无效。需要使用kill命令来发送信号
前–后台切换方法:
CTRL+Z快捷键 --- 把前台程序放到后台(放到后台以后程序就不运行了),通过bg 作业编号 --把后台停止的作业恢复成后台运行态
作业编号的查询:jobs命令
或者 kill -18 %作业编号
后台运行–>后台停止:
发送19信号: kill -19 %作业编号 作业编号:jobs命令
后–前切换方法;
fg 作业编号
后台执行的作用:
前台执行都是按照循序执行的,后台执行可以实现并行执行
后台执行的任务在终端关闭以后也会随之关闭。
实现窗口关闭还继续执行的方法;
方法一:screen命令
程序执行之前开启screen:格式:screen
然后再输入要执行的命令
方法二:nohup命令
格式:nohhup 要执行的程序 -- 会有输出的信息
并行执行的实现:
并行执行:让多个进程同时执行
方法一:把他们都放到后台去执行
方法二:(f1.sh&);(f2.sh&);(f3.sh&) --小括号括起来,分号隔开
方法三:f1.sh&f2.sh&f3.sh&
范例:扫描ip地址
net=10.0.0
for i in {1..254};do
{
if ping -c1 -W1 $net.$i &> /dev/null;then
echo $net.$i is up
else
echo $net.$i is down
fi
}& #若里面有多个命令,就用花括号就是把它作为一个整体
done
wait #后台执行的进程结束之后,主动退出