进程和进程管理
概念
什么是进程
进程是一个在系统中运行的程序
进程是已启动的可执行程序的运行实例,进程有以下组成部分
- 已分配内存的地址空间
- 安全属性,包括所有权凭据和特权
- 进程代码的一个或多个执行线程
- 进程状态
程序和进程
程序:是可执行的二进制文件,是静态的,如:/bin/date,/usr/sbin/httpd等。
进程:是程序运行的过程,是动态的,有生命周期。
父进程复制自己的地址空间(fork)创建一个新的(子)进程结构。每个新进程分配一个唯一的进程ID(PID),
满足跟踪安全性之需。PID和父进程ID(PPID)是子进程环境的元素,任何进程都可以创建子进程,所有进
程都是第一个系统进程的后代。
进程类型
守护进程:在系统引导过程中启动的进程,跟终端无关的进程
前台进程:跟终端相关,通过终端启动的进程
进程生命周期
一个进程被fork出来后,进入就绪态;当被调度到获得CPU执行时,进入执行态;如果时间片用完或被强占时,进入就绪态;资源得不到满足时,进入睡眠态(深度睡眠或浅度睡眠),比如一个网络程序,在等对方发包,此时不能占着CPU,进入睡眠态,当包发过来时,进程被唤醒,进入就绪态;如果被暂停,进入停止态;执行完成后,资源释放,此时父进程wait4还未收到它的信号,进入僵死态。
即整个周期可能会涉及的状态有:就绪态,执行态,僵死态,停止态,睡眠态。
进程状态
在三态模型中,进程状态分为三个基本状态,即运行态,就绪态,阻塞态。
在五态模型中,进程分为新建态、终止态,运行态,就绪态,阻塞态。
就绪态
进程准备就绪,等待被CPU执行时的状态。即进程已经具备运行条件,但是CPU还没有分配过来,需等待被CPU调度到,进入执行态。
执行态:占用CPU,在CPU上执行。
僵死态
进程结束时,其他资源都释放,只留下了task_struct,等待父进程wait4函数处理时的状态。
一个进程如果进入僵死态时,它占用的系统资源都已释放了,只是保留了task_struct等待父进程处理。
如果一个进程一直是僵死态,通过kill是无法杀掉的,除非将它的父进程杀掉,它才会消失。
系统中有僵尸态的进程对系统资源来说没影响,可能是你写的程序有问题,未正常退出,使得父进程无法处理。
停止态
人为地暂停进程时的状态。
在linux中,按ctrl+z,当前终端下运行的进程就会进入停止态。
按fg或bg恢复该进程的运行。
fg与bg的区别是:fg是前台运行,bg是后台运行。
睡眠态
睡眠态分浅度睡眠和深度睡眠,区别在于:
浅度睡眠:可以被资源和信号唤醒
深度睡眠:只能被资源唤醒,比如你挂载一个NFS,当NFS服务器挂了时,你对这个挂载做不了任何操作,比如用kill命令发送任何信号都无效,处理的方法是:1.等待NFS服务器恢复;2.重启你的服务器。
进程的内存泄漏
内存泄漏指随着时间的增长,进程的内存使用呈现线性增长的情况,指的是进程一直在运行,运行中申请了内存,但使用完后并没有释放,运行期间每次都申请内存而不释放导致系统内存越来越少的情况。这里要理解内存泄漏的原因不可能是进程死了,内存没释放。因为进程死了之后就变成僵尸, Linux会自动将进程中申请的资源全部释放,只留下 task_struct 让父进程 wait 来查看状态。不可能再占用内存。
systemd
systmed 是一个用户空间的程序,属于应用程序,不属于 Linux内核范畴。Systemd 是 Linux 系统中最新的初始化系统(init)。
Linux内核加载启动后,用户空间的第一个进程就是初始化进程,这个程序的物理文件约定位于 /sbin/init ,当然也可以通过传递内核参数来让内核启动指定的程序。这个进程的特点是进程号为1,代表第一个运行的用户空间进程
centos7上所有的进程都是systemd的后代,systemd的功能繁多,不仅用来管理服务,还可以管理挂载点,定义定时任务等。这些工作都是由编辑相应的配置单元文件完成的。
管理系统服务
systemd的主要命令行工具是systemctl
systemctl [选项] [命令]
systemctl常用命令
命令 | 描述 |
---|---|
systemctl start name.service | 启动服务 |
systemctl stop name.service | 停止服务 |
systemctl restart name.service | 重启服务(没启动的服务会启动) |
systemctl enable name.service | 启用开机自启服务 |
systemctl disable name.service | 停用自启服务 |
systemctl status name.service | 检查服务状态查看服务是否自启 |
一个服务设置为开机启动使用会将 /usr/lib/systemd/system/name.service 软链接到 /etc/systemd/system/ ,但是 enable 命令不会重写已经存在的链接,所以当我们修改了服务文件就需要重新加载:
systemctl reenable name.service
进程管理常用命令
ps
ps命令用于显示当前进程的状态,类似于windows的任务管理器
选项
ps [选项]
- a :显示终端上的所有进程,包括其他用户地进程
- -A:列出所有的进程
- -e:列出所有的进程
- f:用ASCII字符显示树状结构,表达程序间的相互关系
- -H:以进程层级格式显示进程相关信息
- -w:显示加宽可以显示较多的信息
- -u:显示较详细的信息
- -x:显示其他使用者进程
一般使用:
ps aux
显示信息的格式说明
列名 | 说明 |
---|---|
USER | 进程拥有者 |
PID | 进程ID |
%CPU | 占用的CPU使用率 |
%MEM | 占用的内存使用率 |
VSZ | 占用的虚拟内存大小 |
RSS | 占用的常驻内存大小 |
TTY | 执行的终端编号,直接w可以看到 |
STAT | 该进程的状态 |
START | 进程开始的时间 |
TIME | CPU使用时间 |
COMMAND | 所执行的命令 |
STAT表示的进程状态有如下几种:
- D: 无法中断的休眠状态 ,将一直等待事件的发生或等待某种系统资源
- R: 正在执行中
- S: 可中断状态
- T: 暂停执行
- Z: 不存在但暂时无法消除,也叫僵尸进程
每个进程在运行结束后都会处于僵死状态,等待父进程调用进而释放系统资源,处于该状态的进程已经运行结束,但是它的父进程还没有释放其系统资源 - W: 没有足够的内存可分配
- <: 高优先序的进程
- N: 低优先序的进程
- +:前台进程
- l:多线程进程
- s:主进程(先导进程),有子进程的进程
实例
排序查看所有进程
[root@localhost ~]# ps aux --sort %cpu # 按照CPU使用率递增
[root@localhost ~]# ps aux --sort -%cpu # 递减
[root@localhost ~]# ps aux --sort rss # 按照实际内存使用递增
[root@localhost ~]# ps aux --sort -rss # 递减
按照父子进程显示ssh服务的层级关系
[root@localhost ~]# ps auxf|grep sshd #加f参数
自定义显示格式
[root@localhost ~]# ps -axo user,pid,ppid,%mem,%cpu,command --sort -%cpu #加-o参数
查看指定进程的PID,多种查看的方式
[root@localhost ~]# cat /run/sshd.pid
[root@localhost ~]# ps aux |grep sshd
[root@localhost ~]# pgrep -l sshd
[root@localhost ~]# pidof sshd
查看进程树
[root@localhost ~]# yum install -y psmisc
[root@localhost ~]# pstree
[root@localhost ~]# pstree -p #列出进程ID
top
top命令用于实时显示process的动态
选项
top [选项]
- -d: 改变显示的更新速度,或是在交互式指令列( interactive command)按 s
- -c: 切换显示模式,共有两种模式,一是只显示程序的名称,另一种是显示完整的路径与名称
- -S: 累积模式,会将己完成或消失的子行程 ( dead child process ) 的 CPU time 累积起来
- -s: 安全模式,将交互式指令取消, 避免潜在的危机
- -i: 不显示任何闲置 (idle) 或无用 (zombie) 的行程
- -n: 更新的次数,完成后将会退出 top
- -b: 显示模式,搭配 “n” 参数一起使用,可以用来将 top 的结果输出到文件内
交互模式快捷键
快捷键 | 功能 |
---|---|
空格 | 立即刷新 |
P | 根据CPU使用多少排序 |
T | 根据时间、累计排序 |
q | 退出top命令 |
m | 切换显示内存信息 |
t | 切换显示进程和CPU状态信息 |
c | 切换显示命令名称和完整命令行 |
M | 根据内存的大小排序 |
W | 将当前设置写入 ~/.toprc 文件中,这是top配置文件推荐方法 |
N | 以PID的大小排序 |
z | 彩色 |
实例
显示进程信息,每隔1秒钟刷新一次
[root@localhost ~]# top -d 1
显示完整命令
[root@localhost ~]# top -c
更新两次后终止更新显示
[root@localhost ~]# top -n 2
显示指定的进程信息
[root@localhost ~]# top -p 7085
kill
kill 命令用于删除执行中的程序或工作
kill 可将指定的信号送至程序。预设的信号为 SIGTERM(15),可将指定程序终止
选项
- -l <信号编号>: 若不加<信号编号>选项,则 -l 参数会列出全部的信号名称
- -s <信号名称或编号>:指定要送出的信息
- [程序]:[程序]可以是程序的PID或是PGID
常用信号的编号
编号 | 信号名 | 作用 |
---|---|---|
1 | SIGHUP | 重新加载配置 |
2 | SIGINT | 键盘中断^C |
3 | SIGQUIT | 键盘退出 |
9 | SIGKILL | 强制终止 |
15 | SIGTERM | 正常结束,缺省信号 |
18 | SIGCONT | 继续 |
19 | SIGSTOP | 停止 |
20 | SIGTSTP | 暂停^Z |
实例
杀死所有的ping命令,在linux命令中,使用反引号``包含的命令会优先执行,并将执行的结果作为参数提供给命令。
[root@localhost ~]# kill `pgrep ping`
强制杀死进程(会有残余,资源还没有被回收就直接被终止)
[root@localhost ~]# kill -KILL 123456
[root@localhost ~]# kill -9 123456
重新加载配置
[root@localhost ~]# kill -HUP pid
[root@localhost ~]# kill -1 pid
pkill
pkill 用于杀死一个进程,与 kill 不同的是它会杀死指定名字的所有进程,类似于 killall 命令
选项
pkill [选项] name
- name: 进程名
- -u:指定用户名
- -t:指定终端
实例
结束所有sshd进程
[root@localhost ~]# pkill sshd
结束用户user1的所有进程
[root@localhost ~]# pkill -u user1
终止TTY为pts/2的终端上的所有进程(终端编号TTY可以直接w查看)
[root@localhost ~]# pkill -t pts/2
终止TTY为pts/2的终端上的所有进程,并结束pts/2
[root@localhost ~]# pkill -9 -t pts/2
nice
nice命令用来修改程序的优先级别,如果未指定程序,则会显示目前程序的优先级别,默认的nice值为0,范围为 -20(最高优先级别)到 19(最低优先级别)。
nice数字越小,表示程序会越优先被处理,在系统运行缓慢的时候,nice值越小的进程会有越高的优先处理级别。
Linux进程调度及多任务
每个CPU(或CPU核心)在一个时间点上只能处理一个进程,通过时间片技术,Linux实际能够运行的进程(和线程数)可以超出实际可用的CPU及核心数量。Linux内核进程调度程序将多个进程在CPU核心上快速切换,从而给用户多个进程在同时运行的假象。
通过调整程序在计算机中的优先级别,可以让程序在时间片中占有更长的时间,从而获得更快的处理速度
选项
- -n<nice值>:设置nice值
实例
将ping 的优先级设置为 1 并执行
[root@localhost ~]# nice -n 1 ping www.baidu.com
将 ping 的优先级加 10 并执行,默认是设置为10
[root@localhost ~]# nice ping www.baidu.com
nice值的查看
- 使用top查看nice
NI:实际nice基本
PR:即NI+20,将nice级别显示为映射到更大优先级队列,-20映射到0,+19映射到39 - 使用ps查看nice
其他方法修改nice值
使用top更改, r 调整进程的nice值
[root@localhost ~]# top -p `pgrep ping`
#然后输入r,输入进程id,再输入修改的nice值,回车结束
使用shell更改
[root@localhost ~]# renice -20 8141
8141 (进程 ID) 修改后的nice值为 -20
PRI
在top命令中可以看到有PR这个数值,PR 和 nice 值,都会影响进程执行的优先级。PR 由 OS 内核动态调整,用户不能调整(PR 值越低,进程执行的优先级越高)。
nice值用户可以自己调整,在用户调整了nice值后系统会通过如下公式来调整新的PR值,从而确定这个进程在系统中的优先级
PR(新) = PR(旧) + nice
PR值是OS动态调整的,但是PR的最终值还是需要由OS分析决定的
jobs
jobs 命令可以用来查看当前终端放入后台的任务,注意:jobs只能查看当前终端的任务,如果想要在其他终端也可以看到,就用pstree
- "+"号代表最近一个放入后台的工作,也是工作恢复时默认恢复的工作
- "-"号代表倒数第二个放入后台的工作
前台进程和后台进程
前台进程:前台进程是在终端中运行的命令,该终端为进程的控制终端,前台进程接受键盘产生的输入信号和信号,并允许从终端读取或写入到终端,可以用^C打断。
后台进程:后台进程没有控制终端,它不需要终端的交互,无法用^C打断。
将任务放入到后台
Linux 命令放入后台的方法有两种:
- 在命令后面加入 空格 & 。使用这种方法放入后台的命令,在后台处于执行状态
- 命令执行过裎中按 Ctrl+Z 快捷键,命令在后台处于暂停状态
实例
[root@localhost ~]# top &
[1] 1675
[root@localhost ~]# vim &
[2] 1676
[1]+ 已停止 top
[root@localhost ~]# ping baidu.com > /dev/null & #让ping运行,但是不显示结果
#/dev/null是一个类似于垃圾桶的文件,可以将文件写入到“垃圾桶”中。
[3] 1677
[2]+ 已停止 vim
[root@localhost ~]# jobs
[1]- 已停止 top
[2]+ 已停止 vim
[3] 运行中 ping baidu.com > /dev/null &
将后台任务恢复到前台运行
fg 命令用于把后台工作恢复到前台执行
fg %工作号 #输入jobs后第一列[ ]内的编号就是工作号
注意,在使用此命令时,% 可以省略,但若将% 和工作号全部省略,则此命令会将带有 + 号的工作恢复到前台。另外,使用此命令的过程中, % 可有可无。
实例
[root@localhost ~]# top &
[1] 1674
[root@localhost ~]# jobs
[1]+ 已停止 top
[root@localhost ~]# fg 1
top
top: failed tty set: 被中断的系统调用 #将top恢复到前台,命令虽然是对的,但是top这种需要交互的任务是无法后台的,所以也恢复不了。直接被系统调用中断。
后台任务恢复到后台运行
前面讲过,使用 Ctrl+z 快捷键的方式,可以将前台工作放入后台,但是会处于暂停状态,可以使用bg命令恢复后台运行
bg %工作号
这里的 % 可以省略
实例
将ping命令暂停到后台,然后恢复后台运行
[root@localhost ~]# ping baidu.com > /dev/null
^Z # 这边按下了Ctrl+z
[1]+ 已停止 ping baidu.com > /dev/null
[root@localhost ~]# jobs
[1]+ 已停止 ping baidu.com > /dev/null
[root@localhost ~]# bg %1
[1]+ ping baidu.com > /dev/null &
[root@localhost ~]# jobs
[1]+ 运行中 ping baidu.com > /dev/null &
nohup
虽然使用&可以将程序放在后台运行,但是一旦关闭远程连接那么程序就会中断,如果我们想要将程序一直保持在后台运行,那么我们可以有如下三个选择:
- 把需要在后台执行的命令加入 /etc/rc.local 文件,让系统在启动时执行这个后台程序。这种方法的问题是,服务器是不能随便重启的,如果有临时后台任务,就不能执行了
vim /etc/rc.local
#!/bin/bash
# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
#
# It is highly advisable to create own systemd services or udev rules
# to run scripts during boot instead of using this file.
#
# In contrast to previous versions due to parallel execution during boot
# this script will NOT be run after all other services.
#
# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
# that this script will be executed during boot.
ping www.baidu.com #加上这一条需要在系统启动时执行的后台程序,不过要给文件/etc/rc.d/rc.local加上x权限
#加上这条命令,那么电脑就开不了机了,因为电脑开机的时候会自动执行这个文件中的程序,执行完毕之后才会正常开机。但是ping www.baidu.com不加次数限制是无限执行下去的,所以这个文件中的程序执行不完,但是可以通过远程连接来打断这个程序的运行,例如使用pkill ping,之后就可以正常开机了。可以远程连接是因为开机时sshd的优先级比执行/etc/rc.local要高,sshd执行了就可以远程连接了。
- 使用系统定时任务,让系统在指定的时间执行某个后台命令。这样放入后台的命令与终端无关,是不依赖登录终端的
- 使用 nohup 命令
nohup 命令&
注意,这里的‘&’表示此命令会在终端后台工作;反之,如果没有‘&’,则表示此命令会在终端前台工作。
实例
让一个任务后台运行
[root@localhost ~]# nohup ping www.baidu.com &
[1] 1701
[root@localhost ~]# nohup: 忽略输入并把输出追加到"nohup.out"
我们退出远程连接,然后重新登录回来,会看到 ping baidu.com 依旧在运行,查看 ~/nohup.out 文件可以看到程序执行输出的内容
[root@localhost ~]# ps aux |grep ping
root 7157 0.0 0.0 149968 1988 ? S 14:12 0:00 ping
baidu.com
[root@localhost ~]# tail -f nohup.out
64 bytes from 220.181.38.251 (220.181.38.251): icmp_seq=7 ttl=128 time=38.6
ms
64 bytes from 220.181.38.251 (220.181.38.251): icmp_seq=8 ttl=128 time=40.4
ms
64 bytes from 220.181.38.251 (220.181.38.251): icmp_seq=8 ttl=128 time=39.4
# 想关掉就pkill ping