标签:
启动方式:
守护进程编程要点
(1)屏蔽有关控制终端操作的信号,防止守护进程正常启动之前,控制终端受到干扰退出或挂起。
for(i = 1; i <= 31; i++) signal(SIGTTOU, SIG_IGN); //忽略所有可以忽略的信号,STGSTOP和SIGKILL不能忽略
(2)在后台运行,为了避免挂起控制终端。方法在进程中创建子进程,并使父进程终止。
if(pid = fork()) exit(0); //父进程结束,子进程继续
(3)脱离控制终端和进程组。用setsid()使子进程成为新的会话组长,彻底脱离从父进程继承下来的控制终端的影响
setsid();
(4)禁止进程重新打开控制终端。只有会话组长能够打开终端,再创建一个子进程,并让父进程退出,这样子进程就不是会话组长了。
if(pid = fork()) exit(0); //父进程结束,子进程继续
(5)关闭打开的文件描述符。一般,不需要从父进程那继承来的文件描述符。
#define NOFILE 256 //不同系统有不同限制 for(i = 0; i < NOFILE; i++) //关闭打开的文件描述符 close(i);
(6)改变当前工作目录。进程活动时,其工作目录所在的文件系统不能卸载。故需要将守候进程的工作目录改变到合适的目录
chdir("/tem");
(7)重设文件创建掩码。防止修改守护进程所创建文件的存储权限
umask(0);
(8)处理SIGCHLD信号(子进程退出信号)。让系统帮助回收僵死进程资源
signal(SIGCHLD, SIG_IGN);
守候进程两种写日志信息的方式
(1)进程直接与日志文件建立联系,即open一个文件,然后write写文件
(2)使用日志守候进程syslogd
void openlog (__const char *__ident, int __option, int __facility):打开当前程序与日志守候进程之间的联系。
参数1:要向每个消息加入的字符串,一般为当前进程名
参数2:描述已打开选项
参数3:消息类型,决定将消息写入那个日志文件中
void closelog(void):关闭与日志守候进程的联系
void syslog (int __pri, __const char * __fmt, ...) :写一条日志信息
参数1:决定日志级别 0系统不可用,1必须立刻报告的 2冲突 3错误 4警告 5普通担忧特殊标识 6消息 7调度级
参数2:日志输出格式,类似printf的第二个参数
int setlogmask (int __mask) :设置当前进程syslog()函数输出消息的默认优先级
#include<unistd.h> #include<signal.h> #include<fcntl.h> #include<sys/syslog.h> #include<sys/param.h> #include<sys/types.h> #include<sys/stat.h> #include<stdio.h> #include<stdlib.h> int init_daemon(const char *pname, int facility) { int pid; int i; signal(SIGTTOU, SIG_IGN); //处理可能的终端信号 signal(SIGTTIN, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGHUP, SIG_IGN); if(pid = fork()) //创建子进程,父进程退出 exit(EXIT_SUCCESS); else if(pid < 0) { perror("fork"); exit(EXIT_FAILURE); } setsid(); //设置新会话组长 if(pid = fork()) //创建子进程,父进程退出 exit(EXIT_SUCCESS); else if(pid < 0) { perror("fork"); exit(EXIT_FAILURE); } for(i = 0; i < NOFILE; ++i) //关闭父进程打开的文件描述符 close(i); open("/dev/null", O_RDONLY); //对标准输入输出全部重定向到/dev/null open("/dev/null", O_RDWR); open("/dev/null", O_RDWR); chdir("/tmp"); //修改主目录 umask(0); //重新设置文件掩码 signal(SIGCHLD, SIG_IGN); //处理子进程退出 openlog(pname, LOG_PID, facility); //与守候进程建立联系,加上进程号,文件名 return; } int main(int argc, char * argv[]) { FILE *fp; time_t ticks; init_daemon(argv[0], LOG_KERN); //执行守候进程函数 while(1) { sleep(1); ticks = time(NULL); //获取当前时间 syslog(LOG_INFO, "%s", asctime(localtime(&ticks))); //写日志信息 } }
可以看到,守候进程在后台运行
运行后我找不到日志写哪了?
还有很奇怪的一点,之后每次我用ps aux|grep Daemon_exp 进程号都会加2 ?
标签:
原文地址:http://www.cnblogs.com/dplearning/p/4679925.html