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