task_struct状态
状态 | 描述 |
---|---|
task_running R | 就绪状态,或正在运行,进程的task_struct出现在一个CPU的可执行队列 ,这是进程在用户空间的唯一状态 |
task_interruptible S | 可中断的睡眠状态,例如进行socket、等待信号量等,task_struct放在某个事件的等待队列 |
task_uninterruptible D | 与task_interruptible类似,不常用且很短暂,区别是这个状态下不响应异步信号,例如kill -9杀不死这个状态的进程,整个状态处理一些特殊的不能被打断的任务 |
task_stopped T | 想进程发送SIGSTOP信号会进入该状态,发送SIGCONT信号会将进程从STOPPED状态转为RUNNING状态 |
task_traced T | 这个状态下的进程被监视(暂停),例如断点调试状态下的进程,该状态下的进程不能响应SIGCONT信号转为RUNNING状态,只能等调试程序退出该进程才会转为RUNNING状态 |
task_dead-EXIT_ZOMBIE Z | 僵尸状态,子进程退出时,会向父进程发送SIGCHLD信号,如果父进程调用wait、waitpid函数就会处理该信号(回收子进程的资源),但如果父进程对信号不理睬,就会遗留下task_struct结构以及少数资源,此时这个子进程就被称为僵尸进程 |
task_dead-EXIT_DEAD | 进程的最终状态,只有极短的时间,之后该进程就会消失 |
僵尸进程
指的就是处于僵尸状态EXIT_ZOMBIE
的进程,父进程未处理子进程退出时的信号,子进程会释放部分资源(例如占用的内存、打开的文件),但也有部分资源不会释放,例如task_struct、thread_info等,PID是有限的,如果有大量僵尸进程,则会导致不能再创建新的进程。
僵尸进程的解决也很简单,一是调用waitpid()函数来响应SIGCHLD信号,二是找到他们的父进程并将其杀死,这些僵尸进程就会变成孤儿进程,init进程调用wait()系统调用释放它们的尸体(资源:PID等)。
孤儿进程
父进程结束退出后,必须保证能为其子进程找到另外的父进程,否则这些子进程就会成为孤儿进程,孤儿进程结束后没有父进程为其收尸,会一直处于僵死状态。
解决方法:给子进程找一个当前线程组的线程作为父亲,如果不行,则就让init进程(PID=1)作为父进程。当然,还要遍历一个子进程链表都给他们这些兄弟进程设置父进程(因为一个父进程不只有一个儿子)。