`
zsxxsz
  • 浏览: 451036 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ACL编程之父子进程机制,父进程守护子进程以防止子进程异常退出

阅读更多

在WIN32平台进行编程时,经常会遇到工作进程因为程序内部BUG而异常退出的现象,当然为了解决此类问题最好还是找到问题所在并解决它,但如果这类导致程序崩溃的BUG并不是经常出现,只有当某种条件发生时才会有,在我们解决BUG的时间里,为了尽最大可能地为用户提供服务可以采用一种父进程守护机制:当子进程异常退出时,守护父进程可以截获这一消息,并立即重启子进程,这样用户就可以继续使用我们的程序了,当然如果子进程的问题比较严重频繁地 DOWN掉,而父进程却不停地重启子进程的话,势必造成用户机系统资源的大量耗费,那我们的程序就如病毒一样,很快耗尽了用户机资源,所以需要父进程能够智能地控制重启子进程的时间间隔。
  本文将给出一个具体的例子(利用ACL库),介绍父、子进程的编程方法。
一、接口介绍
1.1 以守护进程方式运行的接口
创建守护进程的方式非常简单,只需要调用 acl_proctl_deamon_init, acl_proctl_daemon_loop 两个函数即可
接口说明如下:

/**
 * 初始化进程控制框架(仅 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);


1.2 以命令方式来控制守护进程(守护进程即控制进程的意思)
守护进程启动后,可以以命令方式控制守护进程来启动、停止子进程,或查询显示当前正在运行的子进程。
启动子进程:acl_proctl_start_one
停止子进程:acl_proctl_stop_one
停止所有子进程:acl_proctl_stop_all
查询子进程是否在运行:acl_proctl_probe
查询当前所有在运行的子进程:acl_proctl_list
通过守护进程停止所有子进程且守护进程自身退出:acl_proctl_quit

接口说明如下:

/**
 * 以命令方式启动某个子进程
 * @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);


1.3、子进程编写
子进程编程也比较容易,只需在程序初始化时调用 acl_proctl_child 即可,这样子进程就会在硬盘创建自己的信息并与父进程(即守护进程)建立联系。
接口说明:

/**
 * 子进程调用接口,通过此接口与父进程之间建立控制/被控制关系
 * @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);


二、例子
2.1、父进程
程序名:acl_project\samples\proctl\proctld.cpp

// 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);
}


2.2、子进程
acl_project\samples\proctl\proctlc.cpp

// 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 是为了让父进程继续启动
}


2.3、编译、运行
  可以打开 acl_project\win32_build\vc\samples\samples_vc2003.sln,编译其中的 proctlc, proctld 两个工程,便会生成两个可执行文件:proctlc.exe(子进程程序),proctld.exe(父进程程序)。
  先让父进程以守护进程模式启动 proctld.exe,然后运行 proctld.exe -d START {path}/proctlc.exe 通知父进程启动子进程;可以运行 proctld.exe -d LIST 列出当前正在运行的子进程,运行 proctld.exe -d PROBE {path}/proctld.exe 判断子进程是否在运行,运行 proctld.exe -d STOP {path}/proctld.exe 让守护父进程停止子进程,运行 proctld.exe -d QUID 使守护进程停止所有子进程并自动退出。
  另外,从子进程的程序可以看出,每隔5秒子进程就会异常退出,则守护进程便会立即重启该子进程,如果子进程死的过于频繁,则守护进程会延迟重启子进程,以防止太过耗费系统资源。

三、小结
  因为有守护进程保护,就不必担心子进程(即你的工作进程)异常崩溃了,这种父子进程模型可以应用于大多数工作子进程偶尔异常崩溃的情形,如果你的程序 BUG太多,每一会儿就崩溃好多次,建议你还是先把主要问题解决后再使用父子进程,毕竟如果你的程序太过脆弱,虽然父进程能不断地重启你的程序,但你还是不能为用户提供正常服务。这种模型适用于在WIN32平台下,你的程序可能写得比较复杂,程序基本上是比较健壮的,只是会因偶尔某些原因而异常退出的情况。
    关于ACL库的在线帮助可以参照:http://acl.sourceforge.net/

 

   国内镜像:http://git.oschina.net/zsxxsz/acl
      个人微博:http://weibo.com/zsxxsz
   acl 库的下载地址:https://sourceforge.net/projects/acl/

   svn:svn checkout svn://svn.code.sf.net/p/acl/code/trunk acl-code

   github:https://github.com/acl-dev/acl

   QQ 群:242722074

 

分享到:
评论
3 楼 sytpb 2011-08-03  
知道了,我启的不对,得先无参起一个父进程(守护)
2 楼 sytpb 2011-08-03  
void acl_proctl_start_one(const char *progname,
const char *progchild, int argc, char *argv[])
{
const char *myname = "acl_proctl_start_one";
char  ebuf[256], buf[1024];
ACL_VSTREAM *client;
ACL_VSTRING *child_args = NULL;
int   n;

....
.....
client = proctl_client_open(progname);   //此行出错


跟了一个,proctl_client_open怎么还有socket 连接,连接出错,所以异常了。???

1 楼 night_stalker 2009-06-08  
Drb 的 acl 原来是这个意思。

相关推荐

    网络课程设计--ACL编程实现

    在本网络课程设计中,我们将深入探讨ACL(Access Control List,访问控制列表)的编程实现。访问控制列表是网络管理中的重要工具,用于定义和实施网络流量的规则,以实现安全策略。通常,ACL用于控制网络设备上的...

    安全操作系统基于ACL的自主访问控制机制的设计与实现

    ### 安全操作系统基于ACL的自主访问控制机制的设计与实现 ...未来的研究方向可能包括进一步优化ACL的存储和检索机制,以及探索与其他安全机制(如强制访问控制)的结合方式,以构建更加完善的安全操作系统环境。

    VS 2017 C++ 防杀进程

    5. **异常处理**:通过捕获并处理特定的系统异常(如进程结束信号),使程序能够应对并防止被强制关闭。 6. **权限控制**:修改进程的访问控制列表(ACL),限制只有特定账户或权限才能操作该进程。 7. **反调试...

    MTG防止未知IP访问-ACL(对外).docx

    综上所述,MTG网关通过精细的ACL管理和动态黑名单机制,提供了有效的安全防护措施,防止未知IP的非法访问。正确配置和管理这些设置是确保网络安全的关键步骤。同时,了解并掌握串口登录及命令行操作,对于应对紧急...

    基于源MAC地址过滤异常报文的ACL+配置区别

    基于源MAC地址过滤异常报文的ACL+配置区别

    操作系统考卷以及课设内容

    6. **保护与安全**:权限管理、访问控制、权限模型(如capability、ACL),以及操作系统的安全性设计,防止未授权的访问和攻击。 7. **分布式系统**:理解分布式系统的基本概念,如分布式进程通信、负载均衡、复制...

    软院操作系统课设上机报告

    这可能涉及到权限控制、访问控制列表(ACL)以及异常处理机制。 在完成这个课设的过程中,你不仅需要理解理论知识,还需要运用编程语言(如C或C++)实现相关功能。在撰写报告时,确保清晰地描述你的实现过程、遇到...

    01-acl.rar

    标题中的"01-acl.rar"表明这是一个关于访问控制列表(ACL,Access Control List)的压缩文件,可能包含了与Linux和UNIX系统编程相关的源代码。描述指出这是“Linux&UNIX系统编程手册”的源码副本,这暗示我们将会...

    acl框架库是一个C语言网络框架库,主要包含:服务器开发框架、同步异步网络通讯、常用数据结构、进程池线程池、流式xmljson

    这个框架的核心特性包括服务器开发框架、同步和异步网络通信机制、常用的数据结构、进程池和线程池管理,以及流式XML和JSON解析器。以下是对这些关键知识点的详细说明: 1. **服务器开发框架**:ACL框架提供了一套...

    思科ACL基本的配置

    动态ACL是一种利用路由器Telnet验证机制,动态建立临时的ACL,以让用户可以暂时访问内网的一种技术。命令格式为: access-list {100-199} dynamic username [timeout minutes] permit any dest-ip dest-wildcard ...

    Acl.rar_ACL

    ACL是一系列规则的集合,这些规则定义了哪些主体(如用户、进程或网络服务)可以对哪些客体(如文件、目录、网络端口)进行何种级别的操作。ACL超越了传统的用户/组权限模型,提供了一种更加灵活且细致的权限管理...

    ACL从入门到精通

    总的来说,理解并熟练运用ACL是网络管理的关键技能之一,它能有效保护网络资源,防止恶意攻击,同时也是实现网络策略和合规性要求的重要工具。通过不断的实践和学习,你可以逐步精通这一领域。在"ACL从入门到精通"的...

    CISCO的ACL教程 CISCO的ACL教程.ppt

    访问控制列表(Access Control List, ACL)是Cisco网络设备中用于控制网络流量的重要工具,它是一种基于特定条件筛选数据包的机制。通过定义一系列规则,ACL可以决定哪些数据包可以通过路由器或交换机接口,哪些应该...

    锐捷交换机ACL配置

    锐捷交换机访问控制列表(Access Control List, ACL)是一种强大的网络管理工具,它允许管理员对网络流量进行精细控制,以实现安全策略、流量管理和优化。在锐捷交换机上配置基于时间的ACL,可以进一步细化策略,...

    64位进程隐藏

    在日常使用中,应该优先依赖系统提供的安全机制,而不是依赖第三方工具进行进程隐藏,以防止不必要的风险。 总的来说,64位进程隐藏是一个涉及操作系统底层机制的复杂主题,需要深入理解操作系统原理、驱动开发以及...

    Windows内核安全编程

    - 这种设计能有效防止用户程序误操作导致系统崩溃,但也需要良好的权限管理以防止恶意攻击。 3. **进程与线程** - 进程是资源分配的基本单位,每个进程都有独立的地址空间。 - 线程是执行的基本单位,同一进程内...

    标准ACL和扩展ACL.doc

    ACL设计原则和工作过程、标准ACL和扩展ACL的应用、EIGRP路由协议的配置和应用 在本实验中,我们将学习到ACL设计原则和工作过程,以及如何定义和应用标准ACL和扩展ACL。此外,我们还将学习到EIGRP路由协议的配置和...

    5.15作业:acl进程管理.txt

    5.15作业:acl进程管理

    掌握ACL的配置方法

    访问控制列表(Access Control List,简称ACL)是网络设备,特别是路由器和交换机上的一种安全机制,用于控制网络流量的进出,以实现访问控制和网络安全策略。通过配置ACL,可以允许或拒绝特定IP地址、端口或协议的...

    ACL详解

    - **反向ACL**:有时需要在相反方向设置ACL,以确保完全控制网络流量。 访问控制列表是网络管理中的重要工具,正确配置和使用ACL可以有效地保护网络安全,防止未授权访问,并实现精细化的流量控制。理解并熟练掌握...

Global site tag (gtag.js) - Google Analytics