进程、线程、协程

一、名词概念

1、什么是进程(what is process)

       进程是操作系统提供的抽象概念,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。程序是指令、数据及其组织形式的描述,进程是程序的实体。程序本身是没有生命周期的,它只是存在磁盘上的一些指令,程序一旦运行就是进程。

       操作系统对进程的控制和管理通过PCB(Processing Control Block),PCB通常是系统内存占用区中的一个连续存区,它存放着操作系统用于描述进程情况及控制进程运行所需的全部信息(进程标识号,进程状态,进程优先级,文件系统指针以及各个寄存器的内容等),进程的PCB是系统感知进程的唯一实体。

      一个进程至少具有5种基本状态:初始态、执行状态、等待(阻塞)状态、就绪状态、终止状态

2、什么是进程的生命周期(process life cycle)

       父进程复制自己的地址空间(fork)创建一个新的(子)进程结构。每个新进程分配一个唯一的进程ID(PID),满足跟踪安全性之需。PID和父进程PPID是子进程环境的元素,任何进程都可以创建子进程。子进程继承父进程的安全性身份、过去和当前的文件描述符、端口和资源特权、环境变量,以及程序代码。随后,子进程可能exec自己的程序代码。通常,父进程在子进程运行期间处于睡眠(sleeping)状态。当子进程完成时发出(exit)信号请求,在退出时,子进程已经关闭或丢弃了其资源环境,剩余的部分称之为僵停(僵尸Zombie)。父进程在子进程退出时收到信号而被唤醒,清理剩余的结构,然后继续执行其自己的程序代码。

3、进程状态(process states)

       在多任务处理操作系统中,每个CPU(或核心)在一个时间点上只能处理一个进程。在进程运行时,它对CPU 时间和资源分配的要求会不断变化,从而为进程分配一个状态,它随着环境要求而改变,有runing、sleeping、stopped、zombie(僵尸进程)四种状态。CPU处理速度很快,看上去都像是在并发的执行多个进程,这是通过处理器在进程间切换来实现的。操作系统对把CPU控制权在不同进程之间交换执行的机制成为上下文切换(context switch),即保存当前进程的上下文,恢复新进程的上下文,然后将CPU控制权转移到新进程,新进程就会从上次停止的地方开始。因此,进程是轮流使用CPU的,CPU被若干进程共享,使用某种调度算法来决定何时停止一个进程,并转而为另一个进程提供服务。

linux上进程有5种状态:
1. 运行(正在运行或在运行队列中等待)
2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
3. 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
4. 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
5. 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)

4、僵尸进程Zombie(有害)

       一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出。这个子进程就是僵尸进程。任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,那么此时子进程的进程控制块(PCB)仍驻留在内存中不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。

5、孤儿进程

       一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。每当出现一个孤儿进程的时候,内核就把孤 儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init进程就会出面处理它的一切善后工作,因此孤儿进程并不会有什么危害

6、线程

       线程也是操作系统提供的抽象概念,是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,同一进程中的多个线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈和线程本地存储

       系统利用PCB来完成对进程的控制和管理。同样,系统为线程分配一个线程控制块TCB(Thread Control Block),将所有用于控制和管理线程的信息记录在线程的控制块中,TCB中通常包括:线程标志符    一组寄存器    线程运行状态    优先级    线程专有存储区    信号屏蔽

       和进程一样,线程同样有五种状态:初始态、执行状态、等待(阻塞)状态、就绪状态和终止状态,线程之间的切换和进程一样也需要上下文切换,这里不再赘述。

7、进程 VS 线程

    进程是资源的分配和调度的独立单元。进程拥有完整的虚拟地址空间,当发生进程切换时,不同的进程拥有不同的虚拟地址空间。而同一进程的多个线程是可以共享同一地址空间

    线程是CPU调度的基本单元,一个进程包含若干线程。

    线程比进程小,基本上不拥有系统资源。线程的创建和销毁所需要的时间比进程小很多

    由于线程之间能够共享地址空间,因此,需要考虑同步和互斥操作

    一个线程的意外终止会影响整个进程的正常运行,但是一个进程的意外终止不会影响其他的进程的运行。因此,多进程程序安全性更高

8、协程

协程(Coroutine,又称微线程)是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制。协程与线程以及进程的关系见下图所示。

  • 协程可以比作子程序,但执行过程中,子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。协程之间的切换不需要涉及任何系统调用或任何阻塞调用

  • 协程只在一个线程中执行,是子程序之间的切换,发生在用户态上。而且,线程的阻塞状态是由操作系统内核来完成,发生在内核态上,因此协程相比线程节省线程创建和切换的开销

  • 协程中不存在同时写变量冲突,因此,也就不需要用来守卫关键区块的同步性原语,比如互斥锁、信号量等,并且不需要来自操作系统的支持。

协程适用于IO阻塞且需要大量并发的场景,当发生IO阻塞,由协程的调度器进行调度,通过将数据流yield掉,并且记录当前栈上的数据,阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去运行。

二、查看进程(ps和 top)

1、静态查看进程(ps)

1.1 静态查看进程 ps

# ps aux | less
USER        PID    %CPU   %MEM    VSZ      RSS    TTY      STAT    START     TIME    COMMAND
root        1       0.0    0.6   128096    6708     ?       Ss     16:20     0:01    /usr/lib/systemd/systemd
————————————————————————————
VSZ: 占用虚拟内存
RSS:  占用实际内存
TTY: 进程运行的终端   若为pts/0等,则表示由网络连接主机进程
STAT: 进程状态 man ps (/STATE)
NI 进程的NICE值,数值大,表示较少占用CPU时间;
WCHAN 当前进程是否正在進行,若为-表示正在進行;
———————————————————————————
R 运行
S 可中断睡眠 Sleep,(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
D 不可中断睡眠,(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
T 停止的进程
Z 僵尸进程
X 死掉的进程
————————————————————————————
[了解]
Ss s进程的领导者,父进程
S< <优先级较高的进程
SN N优先级较低的进程
R+ +表示是前台的进程组
Sl 以线程的方式运行
L 有些页被锁进内存
s 进程的领导者(在它之下有子进程);
l 多进程的(使用 CLONE_THREAD, 类似 NPTL pthreads);
+ 位于后台的进程组;
————————————————————————————
START: 进程的启动时间  //可以开启vim ,在用date验证。
TIME: 进程占用CPU的总时间

1.2  常用参数 ps -ef   或 ps -aux 

-a 显示终端上的所有进程
-u  以用户为主的格式来显示程序状态
-x 显示没有控制终端的进程,(显示所有程序,不以终端机来区分)
-e 显示所有进程。
-f 全格式。
-h 不显示标题。
-l 长格式。
-w 宽输出。,包括其他用户的进程。
-r 只显示正在运行的进程。

1.3 按占比升降序排列

# ps aux --sort %cpu | less      //--sort排序,升序(小到大)
# ps aux --sort -%cpu |less     //-%CPU降序(-表示降序)
# ps aux --sort rss | less    //以驻留内存升序排序
# ps aux --sort -rss  | less  

1.4 自定义显示字段

# ps axo user,pid,ppid,%mem,command   // xo指定列显示
# ps axo user,pid,ppid,%mem,command | grep httpd
  root 8310 1 0.1 /usr/sbin/httpd
  apache 8311 8310 0.0 /usr/sbin/httpd
  apache 8312 8310 0.0 /usr/sbin/httpd
  apache 8313 8310 0.0 /usr/sbin/httpd
  apache 8314 8310 0.0 /usr/sbin/httpd
  apache 8315 8310 0.0 /usr/sbin/httpd
  apache 8316 8310 0.0 /usr/sbin/httpd
  apache 8318 8310 0.0 /usr/sbin/httpd
  apache 8319 8310 0.0 /usr/sbin/httpd
  root 9236 6798 0.0 grep httpd
# ps axo user,pid,ppid,%mem,%cpu,command --sort -%cpu | less    //针对某些程序,显示某些列,再进行排序。简洁明了

1.5 查看指定进程的PID,四种方法(该处指定进程为sshd)
第一种 cat

$ cat /run/sshd.pid
830

第二种 ps

# ps aux |grep sshd
root 10180 0.0 0.0 7224 1024 ? Ss 16:00 0:00 /usr/sbin/sshd

第三种 pgrep

# pgrep -l sshd
10180  sshd
# pgrep sshd
10180

第四种  pidof

# pidof sshd
10180

top -d 1 -p 10180 (动态查看sshd的进程信息)

1.6 查看进程树 pstree -p

查看进程之间的关系,且包含应用名

$ pstree

$ pstree -p |head -n 30
systemd(1)-+-NetworkManager(3866)-+-{NetworkManager}(3957)
           |                      `-{NetworkManager}(3967)
           |-auditd(3768)---{auditd}(3769)
           |-chronyd(3840)
           |-containerd(4342)-+-containerd-shim(471)-+-weed(491)-+-{weed}(532)
           |                  |                      |           |-{weed}(533)
           |                  |                      |           |-{weed}(534)
           |                  |                      |-{containerd-shim}(472)
           |                  |                      |-{containerd-shim}(473)
           |                  |                      |-{containerd-shim}(474)
           |                  |                      |-{containerd-shim}(475)
           |                  |                      |-{containerd-shim}(476)
           |                  |                      |-{containerd-shim}(477)
           |                  |                      |-{containerd-shim}(478)
           |                  |                      |-{containerd-shim}(520)
           |                  |                      `-{containerd-shim}(531)
           |                  |-containerd-shim(1285)-+-java(1306)-+-{java}(1346

1.7  查看进程运行时间

ps -eo pid,user,lstart,etime,cmd | grep nginx

etime:衡量“挂钟时间”,现在和流程开始之间的差异,即总的运行时间。

4-21:45:32 的意思是进程运行了4天21个小时,45分钟,32秒

32-23:25:22 的意思是进程运行了32天23小时,24分钟,22秒

time:(cputime的别名)衡量CPU忙于执行流程代码的时间。当进程正在等待网络或磁盘或只是休眠时,此计数器不会增加。当进程使用多个线程并行执行某些代码时,此计数器会与占用该进程的CPU数量成比例增加。 time通常远小于etime,除非该过程进行大量计算。

lstart:显示进程的启动时间

ps -eo lstart,pid,cmd |grep nginx|grep -v grep
Fri Jun 12 18:25:09 2020 17485 nginx: worker process
Fri Jun 12 18:25:09 2020 17486 nginx: cache manager process
Wed May 27 00:14:49 2020 27921 nginx: master process /usr/local/openresty/nginx/sbin/nginx

# cat /var/run/nginx.pid
27921

# date -d "`ps -eo lstart,pid,cmd |grep 27921|grep -v grep|awk '{print $1,$2,$3,$4,$5}'`" "+%Y-%m-%d"
2020-05-27

# date -d "`ps -eo lstart,pid,cmd |grep 27921|grep -v grep|awk '{print $1,$2,$3,$4,$5}'`" "+%Y-%m-%d:%H:%M:%S"
2020-05-27:00:14:49

# date -d "`ps -eo lstart,pid,cmd |grep 27921|grep -v grep|awk '{print $1,$2,$3,$4,$5}'`" "+%s"
1590509689

2、top动态查看进程

2.1上半部分:

第一部分:系统整体统计信息
top - 11:45:08 up 18:54,  4 users,  load average: 0.05, 0.05, 0.05 
//当前时间;系统运行时间,时:分;当前登录用户数;系统负载,即任务队列的平均长度。三个数值分别为1分钟 、5分钟 、15分钟
Tasks: 176 total,   1 running, 175 sleeping,   0 stopped,   0 zombie  %Cpu(s):  0.0 us,  0.3 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

total 进程总数   running 正在运行的进程数    sleeping 睡眠的进程数    stopped 停止的进程数    zombie 僵尸进程数
Cpu(s):
 us 用户空间占用CPU百分比
 sy 内核空间占用CPU百分比
 ni 用户进程空间内改变过优先级的进程占用CPU百分比
 id 空闲CPU百分比
 wa 等待输入输出的CPU时间百分比
 hi:硬件CPU中断占用百分比
 si:软中断占用百分比
 st:虚拟机占用百分比
KiB Mem :  3865520 total,  1100000 free,   580268 used,  2185252 buff/cache
KiB Swap:  4063228 total,  4063228 free,        0 used.  2917828 avail Mem (avail Mem表示可用于进程下一次分配的物理内存数量,这个大小一般比free大一点,因为除了free的空间外,系统还能立即释放出一些空间来。)

负载加权值解释:小于1正常
load average: 0.86, 0.56, 0.78 系统最近 1分钟,5分钟,15分钟平均负载

关于buffers的小实验:做个小实验,观察缓存的作用。
  time cp -rf /etc /tmp/etc1
  time cp -rf /etc /tmp/etc1
  注意观察两次复制的时间,大大缩小,是因第二次的数据已经到了buffer了。在top的buffer/cache会有体现。

2.2下半部分:

字段介绍

虚拟内存(VIRT):virtual memory usage :(1、进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等2、假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量需要这些内存,但并没有占满。)

常驻内存(RES):resident memory usage :(1、进程当前使用的内存大小 2、包含其他进程的共享 3、如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反用了多少内存)。

共享内存(SHR):shared memory:(1、除了自身进程的共享内存,也包括其他进程的共享内存  2、计算某个进程所占的物理内存大小公式:RES – SHR)

2.3 进程信息

h|?帮助
M 按内存的使用排序
P 按CPU使用排序
N 以PID的大小排序
R 对排序进行反转
f 自定义显示字段
1 显示所有CPU的负载
< 向前
> 向后
z 彩色,Z设置彩色,使用数字调整
W 保存top环境设置

2.4信号种类

kill -9 pid   强制杀死

kill -1 pid  重新加载配置,进程不会死 等效于kill -HUP

kill -15 pid   正常结束

kill -18 pid 继续

kill -19 pid 停止

三、nice优先级设置(人为可设置nice范围-20到19)

法一 :nice -n -5 sleep 6000 &

发二  :top -d 1 -p pid

按r键 //调整进程的优先级(Nice Level) (-20高) ---0--- (19低)(直接回车)
回车 //确认该程序。
-20
回车  //确认修改nice值。
如果直接使用top,使用R调整nice值,先输入PID,再输入nice值即可。

法三:renice -20 pid

四、杀死僵尸进程

僵尸进程产生的原因?

1、子进程结束后向父进程发出SIGCHLD信号,父进程默认忽略了它
2、父进程没有调用wait()或waitpid()函数来等待子进程的结束
3、网络原因有时会引起僵尸进程;

如何杀死僵尸进程?僵尸进程用kill命令是无法杀掉的,但是可以杀掉僵尸进程的父进程ppid,僵尸ppid挂了之后,僵尸进程就成了孤儿进程,孤儿进程不会占用系统资源,会被init程序收养,然后init程序将其回收。

查看具体僵尸进程:

ps -A -o stat,ppid,pid,cmd |grep -e "^[Zz]"   ps自定义组合输出内容,grep -e 只传递一个参数

-A 参数列出所有进程
-o 自定义输出字段 我们设定显示字段为 stat(状态), ppid(进程父id), pid(进程id),cmd(命令)这四个参数
因为状态为 z或者Z的进程为僵尸进程,所以我们使用grep抓取stat状态为zZ进程 

杀僵尸进程的流程

1.查看所有R相关的进程(R是一个具体的僵尸进程,defunct就是zombie)

2.查看僵尸进程的父进程

3.杀死僵尸进程对应的父进程

4.僵尸进程被回收(top 查看僵尸进程总数为0)

top查看僵尸进程的总数,另外按1可显示所有的cpu核数

一条简单的命令,直接查找僵死进程,然后将父进程杀死

# ps -A -o stat,ppid,pid,cmd | grep -e '^[Zz]' | awk '{print $2}' | xargs kill -9

# ps -e -o ppid,stat | grep Z | cut -d” ” -f2 | xargs kill -9

# kill -HUP  $(ps -A -ostat,ppid | grep -e ’^[Zz]‘ | awk ’{print $2}’)  

kill -HUP:

想要更改配置而不需停止并重新启动服务,则使用该命令。在对配置文件作必要的更改后,发出该命令以动态更新服务配置。

如重启Nginx:
   # kill -HUP `cat /app/nginx/nginx.pid`

https://mp.weixin.qq.com/s/DI1E250H9w1WMiBeq0yzIg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塞北酒鬼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值