学习了就要巩固,写博客是其中一种方式。
先看优雅降级广泛的定义:优雅降级(Gracefuldegradation)是指电脑,机器,电子系统或者是网络在本身大部分已经毁坏或无效的情况下还能保持有限的功能这种能力。(来自http://www.baike.com/wiki/%E4%BC%98%E9%9B%85%E9%99%8D%E7%BA%A7)
本文只是为了用C语言演示优雅降级,所以来看一下局限于本文中优雅降级的描述:守护进程不断生成子进程去完成任务,守护进程崩溃后降级成为当前子进程,当前子进程完成当前任务后化身成为守护进程,继续守护进程未完成的使命。
在本例中,我们先启动一个守护进程(server process),接着守护进程再新建一个子进程(fork child),这时守护进程就进入等待状态(wait for child),等待子进程完成任务。这时可能会发生三种情况:
1、子进程顺利完成任务。
2、子进程未能顺利完成任务。
3、守护进程崩溃并且子进程还在执行任务(未崩溃)。
对于第一和第二种情况都很容易处理,本文主要讨论第三种情况:如何在这种情况下让程序更稳健(robust)。
下图演示了优雅降级(第三种情况)的处理过程:
启动守护进程(server process),创建子进程(fork child),等待子进程(wait for child),这时子进程正在和客户端通信(client request 1,2),由于某种原因守护进程在这个时候崩溃(crash),子进程完成任务后发现父进程已经不存在,这时它必须继承它父亲的任务,升级为守护进程(换句话说就是守护进程降级为当前子进程)。
就像愚公移山的道理,愚公的儿子干活回来发现愚公去世了,这时“愚公”这个称号就传给愚公的儿子,某一天愚公的孙子干活回来发现愚公的儿子去世了,“愚公”这个称号继续传给愚公的孙子,子子孙孙,无穷尽也。
说来绕口,直接看代码:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int status;
int parent_pid;
while(1)
{
parent_pid = getpid();
printf("Father: I am %d\n", getpid());
status = -1;
if(fork() == 0)
{
printf("===> Child: I am %d\n", getpid());
printf("===> <<< doing something...... >>>\n");
sleep(8); //子进程在执行任务
parent_pid = getppid(); //任务执行完毕后检查父进程是否还存在:如果父进程已经不存在,那当前子进程已经被init接管,这时getppid()返回1,否则返回父进程的pid。
printf("===> Child: My father is %d\n", parent_pid);
if(parent_pid != 1)
{
printf("My father is alive.\n");
exit(0);
}
else
{
printf("My father is dead. I must continue my fathers Tasks.\n");
}
}
else
{
wait(&status);
//这里可以检查一下子进程的返回状态,看它是否顺利完成任务,没有完成的话就让等下新建的子进程进程完成。
//......
}
}
return 0;
}
编译运行,观察输出可以看到守护进程的pid,子进程执行任务需要8秒,所以我们有足够的时间kill掉守护进程,kill掉守护进程之后子进程会输出"My father is dead. I must continue my fathers Tasks.",演示输出如下:
Father: I am 5070 # 这时守护进程pid为5070
===> Child: I am 5071 # 这时子进程pid为5071
===> <<< doing something...... >>> # 这时在另外一个终端偷偷kill掉守护进程:kill 5070
Beendet # 守护进程(5070)被kill掉的提示
===> Child: My father is 1 # 这时看到当前子进程的父进程变成了init
My father is dead. I must continue my fathers Tasks.
Father: I am 5071 # 和第二行的输出比较可知,子进程(5071)已经成为守护进程。
===> Child: I am 5073
===> <<< doing something...... >>>
===> Child: My father is 5071
My father is alive.
Father: I am 5071
===> Child: I am 5074
===> <<< doing something...... >>>
===> Child: My father is 5071
My father is alive.
Father: I am 5071
===> Child: I am 5075
===> <<< doing something...... >>>
上面的程序会一直进行下去,要想结束它们,必须同时kill守护进程和子进程:kill [parent_pid] [child_pid]