进程状态:
-
R(Running,运行): 进程是可执行的。他或者正在执行,或者在运行队列中等待执行。
int main() { while(1) { } }
-
S(Sleep,可中断): 进程正在睡眠(也就是说它被阻塞),等待某些条件的达成。一旦这些条件达成,内核就会把进程状态设置为运行。处于此状态的进程也会应为接收到信号而提前被唤醒并随时准备投入运行。
int main() { while (1) { getchar(); } }
-
D(不可中断):不可被唤醒的睡眠状态,除了就算是接收到信号也不会被唤醒或准备投入运行外,这个状态与可打断状态相同。这个状态通常必须在等待时不受到干扰或等待事件很快就会发生时出现。由于出于此状态的任务对信号不作响应,所以较之可中断的状态,使用的较少。
#include <unistd.h> int main() { if (!vfork()) { while(1){} } }
-
T(停止状态):可能在任务控制(后台暂停)或跟踪(traced)状态。task_struct 进程描述符state: _TASK_TRACED _TASK_STOPPED
这种状态你在进行gdb调试或者在运行程序的时候control+z
就出现了。 -
Z(Zmobile,僵尸状态):进程已经终止但无法删除至内存外。
僵尸状态是在子进程死了之后父进程并没有进行资源回收,子进程所出现的状态,如果直到父进程死亡,都没有执行wait()系列函数,子进程将交由init(system)进程收养,进行资源回收.#include <unistd.h> int main() { if (!fork()) { while(1); }
D状态之fork()与vfork()的区别
- fork()的写时拷贝
传统的fork()系统调用直接把所有的资源复制给新创建的进程。这种实现过于简单并且效率低下,因为它拷贝的数据也许并不共享,更糟的情况是,如果新进程打算立即执行一个新的映像,那么所有的拷贝将前功尽弃。Linux的fork()使用写时拷贝(copy-on-write)页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。只有在需要写入的时候,数据才会被复制。从而各个进程拥有各自的拷贝。也就是说,资源的复制只有在需要写入的时候才进行,在此之前,只是以只读的方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入才进行。在也根本不会被写入的情况下,他们就无须复制了。 - vfork()
除了不拷贝页表项外,vfork()系统调用和fork()的功能相同。子进程作为父进程的一个单独的线程在它的地址空间里运行,父进程被阻塞,知道子进程退出或执行exec().
僵尸状态与孤儿状态
- 僵尸状态是指子进程先与父进程死亡后,父进程并没有执行wait()系列函数进行资源回收。
- 孤儿状态是指父进程先于子进程死亡后,子进程运行结束后,有pid = 1的首进程进行资源回收。