首先呢,我们来认知一下程序和进程。程序是为实现特定目标或解决特定问题而用计算机语言编写的命令序列的集合。而进程是操作系统对一个正在运行着的程序的一种抽象。
我呢是下面这样来理解程序与进程的区别的,有不全面的地方多多指教。
PCB是什么呢?下面我们就来详细聊聊这PCB。
每个进程在内核中都有一个
进程控制块(PCB)来维护进程相关的信息。其作用是使一个在多道程序环境下不能独立运行的程序成为一个能独立运行的基本单位或其他进程并发执行的进程。PCB是系统感知进程存在的唯一标识。Linux内核的进程控制块是
task_struct结构体。task_struct是Linux内核的一种数据结构。它会被装载到RAM里并且包含着进程的信息。它定义在linux-2.6.38.8、include/linux/sched.h文件中。task_steuct结构体包含了以下内容:
进程标识符(PID)
每个进程都有进程标识符,用户标识符,组标识符。内核通过这个标识符来识别不同的进程,同时,PID也是内核提供给用户程序的接口,用户通过PID对进程发号施令。PID是32位的无符号整数,他被顺序编号:新创建进程的PID通常是前一个进程的PID加1,然而,为了与16位硬件平台的传统Linux系统保持兼容,在Linux上允许的最大PID是32767,当内核在系统中创建第32768个进程时,就必须重新开始使用已闲置的PID。即最多可运行32767个进程。
进程状态
可运行状态
处于这种状态的进程,要么正在运行、要么正准备运行。正在运行的进程就是当前进程(由current所指向的进程),而准备运行的进程只要得到CPU就可以立即投入运行,CPU是这些进程唯一等待的系统资源。系统中有一个运行队列(run_queue),用来容纳所有处于可运行状态的进程,调度程序执行时,从中选择一个进程投入运行。在后面我们讨论进程调度的时候,可以看到运行队列的作用。当前运行进程一直处于该队列中,也就是说,current总是指向运行队列中的某个元素,只是具体指向谁由调度程序决定。
等待状态
处于该状态的进程正在等待某个事件(event)或某个资源,它肯定位于系统中的某个等待队列(wait_queue)中。Linux中处于等待状态的进程分为两种:可中断的等待状态和不可中断的等待状态。处于可中断等待态的进程可以被信号唤醒,如果收到信号,该进程就从等待状态进入可运行状态,并且加入到运行队列中,等待被调度;而处于不可中断等待态的进程是因为硬件环境不能满足而等待,例如等待特定的系统资源,它任何情况下都不能被打断,只能用特定的方式来唤醒它,例如唤醒函数wake_up()等。
暂停状态
此时的进程暂时停止运行来接受某种特殊处理。通常当进程接收到SIGSTOP、SIGTSTP、SIGTTIN或 SIGTTOU信号后就处于这种状态。例如,正接受调试的进程就处于这种状态。
僵死状态
进程虽然已经终止,但由于某种原因,父进程还没有执行wait()系统调用,终止进程的信息也还没有回收。顾名思义,处于该状态的进程就是死进程,这种进程实际上是系统中的垃圾,必须进行相应处理以释放其占用的资源。
定义状态
优先级
相对于其他进程的优先级。
程序计数器
下一句要执行的指令地址。
内存指针
包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
上下文数据
进程执行时处理器的寄存器中的数据。上下文数据,也称处理器相关的环境信息。进程作为一个执行环境的综合,当系统调度某个进程执行,即为该进程建立完整的环境时,处理器的寄存器、堆栈等是必不可少的。因为不同的处理器对内部寄存器和堆栈的定义是不尽相同的,所以也叫“处理机状态”。当进程暂停时,处理机状态必须保存到进程的task_struct结构中,当进程被调度重新运行时再从中恢复这些环境,也就是恢复这些寄存器和堆栈的值。
struct thread_struct *tss; //任务切换状态
I/O状态信息
包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息
又称会计信息。如CPU与实际时间之使用数量、时限、账号、工作或进程号码。
注:Unix系统中把进程控制块分为proc结构和user结构(U区)两部分。proc存放的是系统经常要查询和修改的信息,需要快速访问,因此将其放入内存。user结构存放那些只在进程运行时才用到的控制信息。
Windows中的控制进程快是EPROCESS结构。