相信随着Linux的普及,大家都在写不少Linux下的程序了,尤其是一些服务端程序慢慢地都转到Linux下了吧。大家必然碰到问题是如何让自己的进程成为守护进程,在系统启动的时候运行,并且永远是后台进程。下面就写一个这样的程序了。
源代码如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | //////////////////////////////init_daemon.c 开始/////////////////////////////////////////// #include <unistd.h> #include <signal.h> #include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> /********************************************************************* *filename: init_daemon.c *purpose: 产生后台进程 *wrote by: zhoulifa([email protected]) 周立发(http://zhoulifa.bokee.com) *date time:2006-03-10 01:00:00 *Thanks to: 北京工业大学 小胡(本文摘自http://www.qtcn.org/bbs/simple/index.php?t116.html) *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 *                         但请遵循GPL *********************************************************************/ void init_daemon(void) { 	int pid; 	int i; 	if (pid = fork()) 		exit(0);				//是父进程,结束父进程 	else if (pid < 0) 		exit(1);				//fork失败,退出 //是第一子进程,后台继续执行 	setsid();					//第一子进程成为新的会话组长和进程组长 //并与控制终端分离 	if (pid = fork()) 		exit(0);				//是第一子进程,结束第一子进程 	else if (pid < 0) 		exit(1);				//fork失败,退出 //是第二子进程,继续 //第二子进程不再是会话组长 	for (i = 0; i < NOFILE; ++i)	//关闭打开的文件描述符 		close(i); 	chdir("/tmp");				//改变工作目录到/tmp 	umask(0);					//重设文件创建掩模 	return; } //////////////////////////////init_daemon.c 结束/////////////////////////////////////////// | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 上面这是个通用的函数,可以让你的程序成为后台守护进程。下面是一个测试程序: //////////////////////////////daemontest.c 开始/////////////////////////////////////////// #include <stdio.h> #include <time.h> /********************************************************************* *filename: daemontest.c *purpose: 测试后台进程 *wrote by: zhoulifa([email protected]) 周立发(http://zhoulifa.bokee.com) *date time:2006-03-10 01:09:00 *Thanks to: 北京工业大学 小胡(本文参考了其文章http://www.qtcn.org/bbs/simple/index.php?t116.html) *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 *                         但请遵循GPL *********************************************************************/ void init_daemon(void);			//守护进程初始化函数 void signal_reload(int signal) { /*当收到SIGUSR1信号时程序重新导入所有参数*/ 	FILE *fp; 	time_t t; 	if ((fp = fopen("test.log", "a")) >= 0) { 		t = time(0); 		fprintf(fp, "I received signal(%d), reload all parameters at %s\n", signal, asctime(localtime(&t))); 		fclose(fp); 	} /*重新导入参数*/ } void signal_handle(int signal) { /*当收到SIGUSR2信号时程序退出*/ 	FILE *fp; 	time_t t; 	if ((fp = fopen("test.log", "a")) >= 0) { 		t = time(0); 		fprintf(fp, "I received signal(%d), exit at %s\n", signal, asctime(localtime(&t))); 		fclose(fp); 	} 	exit(0); } int main(int argc, char **argv) { 	FILE *fp; 	time_t t; 	init_daemon();				//初始化为Daemon 	signal(SIGCHLD, SIG_IGN);	/*忽略子进程退出信号,若在此之后又产生了子进程, 								   如果不处理此信号,将在子进程退出后产生僵尸进程 */ 	signal(SIGUSR1, signal_reload);	/*处理SIGUSR1信号,可以定义此信号为重导参数信号 */ 	signal(SIGUSR2, signal_handle);	/*处理SIGUSR2信号,可以定义此信号为退出信号 */ 	while (1)					//每隔一分钟向test.log报告运行状态 	{ /*这是各位程序的主体部分,所以的工作在下面完成,比如http服务、FTP服务等*/ 		sleep(60);				//睡眠一分钟 		if ((fp = fopen("test.log", "a")) >= 0) {	/*注意,由于在init_daemon里面已经把路径切换到了/tmp,因此此文件是/tmp/test.log */ 			t = time(0); 			fprintf(fp, "I'm here at %s\n", asctime(localtime(&t))); 			fclose(fp); 		} 	} } //////////////////////////////daemontest.c 结束/////////////////////////////////////////// | 
编译时使用命令进行联合编译:
gcc init_daemon.c daemontest.c
产生了一个程序比如叫a.out
你就可以运行此程序了./a.out了。
如果想要此程序在系统启动时自动运行,你可以在/etc/rc.d/rc.local里面用su命令加上一行,比如:
su – Jacky -c “/bin/a.out”
这个命令将以Jacky用户身份运行/bin/a.out程序
程序运行过程中如果你修改了程序的参数,则必然希望程序重新导入参数,那么你可以用ps命令查看程序的进程号:
ps -ef|grep a.out
然后用kill命令向程序发参数,比如:
kill -s SIGUSR1 11422
同理,如果想要终止程序,则向程序发SIGUSR2信号:
kill -s SIGUSR2 11422
发表评论
要发表评论,您必须先登录。