相信随着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
发表评论
要发表评论,您必须先登录。