目录
基本概念
进程控制块-PCB
进程信息
task_struct内容分类
标示符
进程状态
细分的进程状态
程序计数器
上下文信息
内存指针
IO信息
记账信息
fork创建子进程
fork的使用
代码模拟
原理
僵尸进程
僵尸进程的产生
代码模拟
僵尸进程的危害&如何解决
解决方案
孤儿进程
孤儿进程的产生
代码模拟
含义
进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。 Linux中的PCBLinux操作系统下的PCB是:task_struct。task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。
进程信息也可以进入/proc 系统文件夹查看:
那么如何查看我们自己写的代码被加载到内存后的进程信息?先来看如下代码:
要查看自己写的代码进程信息,首先要保证代码的运行时间够长,如果运行时间太短,那么查看时进程就已经退出,查看不到了。以上代码中我使用了死循环,将test.c文件进行编译生成test文件运行后,使用命令 ps aux | grep test 就可以查看到进程信息。如果要停止运行,在执行的界面输入:Ctrl+c 就可以结束当前进程。
2.getppid()的返回值是当前进程的父进程的PID,与getpid()功能类似。
站在CPU的角度,进程状态可以分为:运行、就绪、阻塞。
运行:进程占用CPU,正在使用CPU来执行自己的代码
就绪:进程已经具备运行条件,但是CPU没有分配过来。
阻塞:进程等待某种资源,而不能运行。例如:等待IO输入。
用一幅图来直观的理解:
3. D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。此状态难以模拟。
4.T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
运行如下代码后,按下Ctrl+z,可以暂停进程,如果想要恢复,按下f+g即可:
5.t跟踪状态:调试程序的时候可以看到。
如下代码,编译时加上-g选项后,生成可调式的test文件,使用gdb调试,打上断点,让程序运行起来,然后查看进程状态,就可以看得到了。
6.X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
7.僵尸状态(Zombies)是一个比较特殊的状态。当进程退出,并且父进程没有读取到子进程退出的返回代码时,就会产生僵尸进程。
作用:保存程序中即将被执行的下一条指令的地址。
一个进程不一定一直占用CPU资源,当代码没有执行完时,可能会被从CPU当中剥离出来,将CPU资源让其他进程使用,当再一次拥有CPU资源后,程序计数器的作用就体现了,代码可以从上一次中断的位置开始执行。
作用:保存进程执行时处理器的寄存器中的数据。
当进程切换时,保存数据,为下一次在执行做准备。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
fork是用来创建子进程的:
可以发现,fork()返回给父进程的值是子进程的PID
1.子进程拷贝父进程的PCB
2.父子进程代码共享
3.数据独有
注意:父子进程在运行的时候是互不干扰的,子进程的代码是从fork()之后开始执行的,不执行fork()语句。主要依靠程序计数器来完成。
子进程的PCB一直得不到释放,从而造成了内存泄漏。
1.杀死父进程(不推荐)
2.重启操作系统(不推荐)
3.进程等待(属于进程控制章节)
如下代码中,父进程先退出,子进程变成了孤儿进程,后被1号进程领养。
切记:没有孤儿状态。孤儿进程没有危害