精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-06-07
最后修改:2009-08-19
在WIN32平台进行编程时,经常会遇到工作进程因为程序内部BUG而异常退出的现象,当然为了解决此类问题最好还是找到问题所在并解决它,但如果这类导致程序崩溃的BUG并不是经常出现,只有当某种条件发生时才会有,在我们解决BUG的时间里,为了尽最大可能地为用户提供服务可以采用一种父进程守护机制:当子进程异常退出时,守护父进程可以截获这一消息,并立即重启子进程,这样用户就可以继续使用我们的程序了,当然如果子进程的问题比较严重频繁地 DOWN掉,而父进程却不停地重启子进程的话,势必造成用户机系统资源的大量耗费,那我们的程序就如病毒一样,很快耗尽了用户机资源,所以需要父进程能够智能地控制重启子进程的时间间隔。 /** * 初始化进程控制框架(仅 acl_proctl_start 需要) * @param progname {const char*} 控制进程进程名 */ ACL_API void acl_proctl_deamon_init(const char *progname); /** * 控制进程作为后台服务进程运行,监视所有子进程的运行状态, * 如果子进程异常退出则会重启该子进程 */ ACL_API void acl_proctl_daemon_loop(void);
/** * 以命令方式启动某个子进程 * @param progname {const char*} 控制进程进程名 * @param progchild {const char*} 子进程进程名 * @param argc {int} argv 数组的长度 * @param argv {char* []} 传递给子进程的参数 */ ACL_API void acl_proctl_start_one(const char *progname, const char *progchild, int argc, char *argv[]); /** * 以命令方式停止某个子进程 * @param progname {const char*} 控制进程进程名 * @param progchild {const char*} 子进程进程名 * @param argc {int} argv 数组的长度 * @param argv {char* []} 传递给子进程的参数 */ ACL_API void acl_proctl_stop_one(const char *progname, const char *progchild, int argc, char *argv[]); /** * 以命令方式停止所有的子进程 * @param progname {const char*} 控制进程进程名 */ ACL_API void acl_proctl_stop_all(const char *progname); /** * 探测某个服务进程是否在运行 * @param progname {const char*} 控制进程进程名 * @param progchild {const char*} 子进程进程名 */ ACL_API void acl_proctl_probe(const char *progname, const char *progchild); /** * 列出当前所有正在运行的服务进程 * @param progname {const char*} 控制进程进程名 */ ACL_API void acl_proctl_list(const char *progname); /** * 以命令方式通知控制进程停止所有的子进程,并在子进程退出后控制进程也自动退出 * @param progname {const char*} 控制进程进程名 */ ACL_API void acl_proctl_quit(const char *progname);
/** * 子进程调用接口,通过此接口与父进程之间建立控制/被控制关系 * @param progname {const char*} 子进程进程名 * @param onexit_fn {void (*)(void*)} 如果非空则当子进程退出时调用的回调函数 * @param arg {void*} onexit_fn 参数之一 */ ACL_API void acl_proctl_child(const char *progname, void (*onexit_fn)(void *), void *arg);
// proctld.cpp : 定义控制台应用程序的入口点。 // #pragma comment(lib,"ws2_32") #include "lib_acl.h" #include <assert.h> static void init(void) { acl_init(); // 初始化ACL库 } static void usage(const char *progname) { printf("usage: %s -h [help] -d [START|STOP|QUIT|LIST|PROBE] -f filepath -a args\r\n", progname); getchar(); } int main(int argc, char *argv[]) { char ch, filepath[256], cmd[256]; char **child_argv = NULL; int child_argc = 0, i; ACL_ARGV *argv_tmp; filepath[0] = 0; cmd[0] = 0; init(); while ((ch = getopt(argc, argv, "d:f:a:h")) > 0) { switch(ch) { case 'd': ACL_SAFE_STRNCPY(cmd, optarg, sizeof(cmd)); break; case 'f': ACL_SAFE_STRNCPY(filepath, optarg, sizeof(filepath)); break; case 'a': argv_tmp = acl_argv_split(optarg, "|"); assert(argv_tmp); child_argc = argv_tmp->argc; child_argv = (char**) acl_mycalloc(child_argc + 1, sizeof(char*)); for (i = 0; i < child_argc; i++) { child_argv[i] = acl_mystrdup(argv_tmp->argv[i]); } child_argv[i] = NULL; acl_argv_free(argv_tmp); break; case 'h': usage(argv[0]); return (0); default: usage(argv[0]); return (0); } } if (strcasecmp(cmd, "STOP") == 0) { // 向守护进程发送消息命令,停止某个子进程或所有的子进程 if (filepath[0]) acl_proctl_stop_one(argv[0], filepath, child_argc, child_argv); else acl_proctl_stop_all(argv[0]); } else if (strcasecmp(cmd, "START") == 0) { if (filepath[0] == 0) { usage(argv[0]); return (0); } // 向守护进程发送消息命令,启动某个子进程 acl_proctl_start_one(argv[0], filepath, child_argc, child_argv); } else if (strcasecmp(cmd, "QUIT") == 0) { // 向守护进程发送消息命令,停止所有的子进程同时守护父进程也退出 acl_proctl_quit(argv[0]); } else if (strcasecmp(cmd, "LIST") == 0) { // 向守护进程发送消息命令,列出由守护进程管理的正在运行的所有子进程 acl_proctl_list(argv[0]); } else if (strcasecmp(cmd, "PROBE") == 0) { if (filepath[0] == 0) { usage(argv[0]); return (0); } // 向守护进程发送消息命令,探测某个子进程是否在运行 acl_proctl_probe(argv[0], filepath); } else { // 父进程以守护进程方式启动 char buf[MAX_PATH], logfile[MAX_PATH], *ptr; // 获得父进程执行程序所在的磁盘路径 acl_proctl_daemon_path(buf, sizeof(buf)); ptr = strrchr(argv[0], '\\'); if (ptr == NULL) ptr = strrchr(argv[0], '/'); if (ptr == NULL) ptr = argv[0]; else ptr++; snprintf(logfile, sizeof(logfile), "%s/%s.log", buf, ptr); // 打开日志文件 acl_msg_open(logfile, "daemon"); // 打开调试信息 acl_debug_init("all:2"); // 以服务器模式启动监控进程 acl_proctl_deamon_init(argv[0]); // 父进程作为守护进程启动 acl_proctl_daemon_loop(); } if (child_argv) { for (i = 0; child_argv[i] != NULL; i++) { acl_myfree(child_argv[i]); } acl_myfree(child_argv); } return (0); }
// proctlc.cpp : 定义控制台应用程序的入口点。 // #pragma comment(lib,"ws2_32") #include "lib_acl.h" static void onexit_fn(void *arg acl_unused) { printf("child exit now\r\n"); } int main(int argc, char *argv[]) { int i; acl_socket_init(); acl_msg_open("debug.txt", "proctlc"); acl_msg_info(">>> in child progname(%s), argc=%d\r\n", argv[0], argc); if (argc > 1) acl_msg_info(">>> in child progname, argv[1]=(%s)\r\n", argv[1]); // 子进程启动,同时注册自身信息 acl_proctl_child(argv[0], onexit_fn, NULL); for (i = 0; i < argc; i++) { acl_msg_info(">>>argv[%d]:%s\r\n", i, argv[i]); } i = 0; while (1) { acl_msg_info("i = %d\r\n", i++); if (i == 5) break; else sleep(1); } return (-1); // 返回 -1 是为了让父进程继续启动 }
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-06-08
Drb 的 acl 原来是这个意思。
|
|
返回顶楼 | |
浏览 3107 次