赞
踩
目录
什么是等待队列,什么是运行队列,什么是挂起/阻塞,什么叫唤醒进程
从操作系统宏观的概念上讲,进程有三种状态,就绪态,运行态和阻塞态,进程初始化完成后进入就绪态,然后操作系统就会从就绪的进程中调度进程给CPU执行,在CPU中运行的进程就处于运行态,当时间片完后又会变成就绪态在运行队列里面等待CPU下次调度;如果在运行中的进程需要某种外设或某些资源但是无法满足时(比如发起IO请求),处于运行态的进程就会进入阻塞态,等到运行条件满足以后,变为就绪态等待系统调用。
在Linux系统中,进程的状态有六种:R,S,D,T,X,Z
1.进程的状态信息在task_struct(PCB)里面
2.进程状态的意义:方便OS快速判断进程的状态,完成特定的功能,比如调度,本质是一种分类
让进程一直运行,通过ps指令查看当前进程的状态是R+,也就是运行状态(+表示处于前台的进程,如果我们想在后台运行进程./test6 &,这样在运行的时候加一个&即表示在后台)
- #include <iostream>
- using namespace std;
- int main()
- {
- while (1)
- {
- // cout << "running";
- }
- return 0;
- }
- [zebra@VM-8-12-centos cpp]$ ps -axj | head -1 && ps -axj | grep test6 | grep -v grep
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 3565 9911 9911 3565 pts/4 9911 R+ 1001 3:56 ./test6
进程等待用户输入的时候,会进入S状态
- #include <iostream>
- using namespace std;
- int main()
- {
- int t;
- while (1)
- {
- cin >> t;
- }
- return 0;
- }
- [zebra@VM-8-12-centos cpp]$ ps -axj | head -1 && ps -axj | grep test6 | grep -v grep
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 3565 11425 11425 3565 pts/4 11425 S+ 1001 0:00 ./test6
D状态是一种不可中断的睡眠状态。比如一个进程让磁盘你帮我写1G数据到磁盘里面去,磁盘开始忙了,进程就会进入D状态等待磁盘写入完成(因为这种等待状态是不允许被中断的,因为如果中断进程的等待,磁盘写入数据完成后,无法向原来的进程返回错误/正确信息,会导致一些问题)
D状态就是深度睡眠,处于这种状态的进程不能被中断的(不可以被杀掉)
进程在内核中某些不能被信号打断,例如对某些硬件设备进行操作时刻(等待磁盘Io,等待网络io等等)。
进程处于D状态一般情况下很短暂,不应该被top或者ps看到。
如果进程在top和ps看到长期处于D状态,那么可能进程在等待IO时出现了问题导致进程一直等待不到IO资源,此时如果要处理掉这个D进程,那么只能重启整个系统才会恢复。因为此时整个进程无法被kill 掉。
处于S状态的进程里面的数据可能会被更新,然后唤醒,处于T状态的进程是一种暂停状态,是彻底暂停了,也不会对其里面的一些数据进程更新。
所以当一个要进程退出的时候,会先进入Z僵尸状态,将进程的退出信息保存在task_struct里面,供父进程或者操作系统读取该信息,之后才会进入X死亡状态。
模拟子进程执行结束,父进程还没有结束的情况,此时子进程会变成僵尸进程,也就是处于Z状态。(后5s)
- #include <iostream>
- #include <cstdlib>
- #include <unistd.h>
- using namespace std;
- int main()
- {
- pid_t id = fork();
- if (id == 0)
- {
- // 子进程
- cout << "这是子进程" << endl;
- sleep(5);
- }
- else if (id > 0)
- {
- // 父进程
- cout << "这是父进程" << endl;
- sleep(10)
- }
- else
- {
- //执行出错
- exit(-1);
- sleep(10);
- }
-
- }
- [zebra@VM-8-12-centos cpp]$ while :; do ps -axj | head -1 && ps -axj | grep test6 | grep -v grep; sleep 1; echo "============================================================="; done
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 Z+ 1001 0:00 [test6] <defunct>
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 Z+ 1001 0:00 [test6] <defunct>
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 Z+ 1001 0:00 [test6] <defunct>
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 Z+ 1001 0:00 [test6] <defunct>
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- 4932 5670 5670 4932 pts/0 5670 S+ 1001 0:00 ./test6
- 5670 5671 5670 4932 pts/0 5670 Z+ 1001 0:00 [test6] <defunct>
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- =============================================================
- PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
- =============================================================
我们把从运行状态的task_struct(run_queue),放到等待队列中,就叫做挂起等待(阻塞)从等待队列,放到运行队列,被CPU调度就叫做唤醒进程
当一个进程在运行的过程中,由于其某些运行条件还没就绪(比如要网络但是网卡了,或者需要等待IO,也就是需要使用外设了),就会被放到等待队列中,并且task_struct里面的状态位也会被改变为S/D。
当进程处于S/D状态的时候,在一个等待队列里面等着使用外设(比如网卡,磁盘显示器等)
等CPU的队列叫做运行队列,等外设的设备叫做等待队列
所谓的进程,在运行的时候,有可能因为运行需要,可以会在不同的队列里
在不同的队列里,所处的状态是不一样的
当一个进程在R状态的时候,如果需要某种外设,但是外设在被使用,我就把你的状态变成S/D,然后把你的task_struct放到等待队列里面去
就绪态/运行态就是R状态,停止对应的就是X/Z状态,阻塞态对应的就是S/D/T状态(T状态很少使用)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。