孤儿进程 僵尸进程

      正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。 当一个 进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。

      孤儿进程:
      一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

      僵尸进程:
      一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。

      孤儿进程是没有父进程的进程,孤儿进程这个重任就落到了init进程身上,init进程就好像是一个民政局,专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候,内核就把孤 儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init进程就会代表党和政府出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。
  任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。 如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。
  
      僵尸进程危害场景:
  例如有个进程,它定期的产生一个子进程,这个子进程需要做的事情很少,做完它该做的事情之后就退出了,因此这个子进程的生命周期很短,但是,父进程只管生成新的子进程,至于子进程 退出之后的事情,则一概不闻不问,这样,系统运行上一段时间之后,系统中就会存在很多的僵尸进程,倘若用ps命令查看的话,就会看到很多状态为Z的进程。
严格地来说,僵死进程并不是问题的根源,罪魁祸首是产生出大量僵死进程的那个父进程。

      解决办法:
      当我们寻求如何消灭系统中大量的僵死进程时,答案就是把产生大 量僵死进程的那个元凶枪毙掉(也就是通过kill发送SIGTERM或者SIGKILL信号)。枪毙了元凶进程之后,它产生的僵尸进程就变成了孤儿进程,这些孤儿进程会被init进程接管,init进程会wait()这些孤儿进程,释放它们占用的系统进程表中的资源,这样,这些已经僵死的孤儿进程就能结束了。

Linux 普通进程 后台进程 守护进程

      普通进程:
      是在前台运行的,这时就把shell给占据了,我们无法进行其它操作。
      后台进程:
      对于那些没有交互的进程,很多时候,我们希望将其在后台启动,可以在启动参数的时候加一个’&'实现这个目的。切换到后台的进程称为job。切换到后台时会输出相关job信息,切换到后台的进程,仍然可以用ps命令查看,或通过jobs命令只查看所有job(后台进程)。后台进程会随着Shell的退出而结束。
      守护进程:
如果一个进程永远都是以后台方式启动,并且不能受到Shell退出影响而退出,一个正统的做法是将其创建为守护进程(daemon)。守护进程值得是系统长期运行的后台进程,类似Windows服务。守护进程信息通过ps –a无法查看到,需要用到–x参数,当使
用这条命令的时候,往往还附上-j参数以查看作业控制信息

      进程查看
            守护进程:ps -x
            普通进程:ps 或 带参数的其他ps命令
            后台进程:jobs 或 前面的上述的那些命令

      跟系统任务相关的几个命令
            fg、bg、jobs、&、ctrl+z

  1. & 最经常被用到
    用在一个命令的最后,可以把这个命令放到后台执行
  2. ctrl + z
    可以将一个正在前台执行的命令放到后台,并且暂停
  3. jobs
    查看当前有多少在后台运行的命令
  4. fg
    将后台中的命令调至前台继续运行
      如果后台中有多个命令,可以用 fg %jobnumber将选中的命令调出,%jobnumber是通过jobs命令查到的后台正在执行的命令的序号(不是pid)
  5. bg 将一个在后台暂停的命令,变成继续执行
    如果后台中有多个命令,可以用bg %jobnumber将选中的命令调出,%jobnumber是通过jobs命令查到的后台正在执行的命令的序号(不是pid)
      1. jobs列举出后台作业信息。([作业号] 运行状态 作业名称)
      2. ctrl+z 将任务放到后台去,并暂停;
      3. bg <%int> 将后台任务唤醒,在后台运行;
      4. fg <%int> 将后任务的程序放到前台;

      在系统调用库中有一个库函数可以直接使一个进程变成守护进程,
       #include <unistd.h>
       int daemon(int nochdir, int noclose);