1:创建子进程并且父进程退出
2:调用setsid()创建一个新会话
3:再次fork()一个子进程,我们称为孙子进程,此时我们确定孙子进程没有控制终端。为什么再fork一次看我另一篇关于会话进程组的博文
http://blog.chinaunix.net/uid-31374636-id-5760998.html
4:当前工作目录更改为根目录chdir("/")
5: 设置文件模式创建屏蔽字umask(0)
6: 关闭打开的文件描述符
7:将标准输入输出,错误输出都定向到/dev/null,这样不会在终端产生任何输出
8:因为stdin,stdout,stderr都定向到/dev/null,所以不能在终端输出,关于出错消息我们只能通过日志记录到文件中
9:使用记录锁保证守护进程只有一个副本在后台运行
只要保证进程的父进程为init,没有控制终端,工作目录最好是根目录,文件描述符都被关闭,文件模式创建屏蔽字为0。最重要的是一直运行,那么它就是守护进程
-
//write a program which change the process to be a daemon
-
#include<unistd.h>
-
#include<fcntl.h>
-
#include<stdio.h>
-
#include<syslog.h>
-
#include<sys/resource.h>
-
#include<sys/stat.h>
-
#include<stdlib.h>
-
-
void daemonize(char*cmd)
-
{
-
pid_t pid;
-
if((pid=fork())<0){
-
perror("fork a child process failed");
-
exit(0);
-
}
-
if(pid!=0)
-
exit(0);
-
//father process have exited,now only the child process
-
//create a session
-
setsid();
-
//maybe this child process has a tty,so i fork again to sure the daemon process have not tty.
-
if((pid=fork())<0){
-
perror("fork a grandchild failed");
-
exit(0);
-
}
-
if(pid!=0)
-
exit(0);
-
//the child process have exited,now only the grandchild process
-
umask(0);
-
if(chdir("/")<0){
-
perror("set work directory to / failed");
-
exit(0);
-
}
-
//now,i will turn off all file discription
-
struct rlimit fd_lim;
-
if(getrlimit(RLIMIT_NOFILE,&fd_lim)<0){
-
perror("can't get file limit");
-
exit(0);
-
}
-
if(fd_lim.rlim_max==RLIM_INFINITY)
-
fd_lim.rlim_max=1024;
-
for(int i=0;i<fd_lim.rlim_max;++i){
-
close(i);
-
}
-
//the last work is redirect the stdin,stdout,stderr to /dev/null and process the error message to log file
-
int fd0,fd1,fd2;
-
fd0=open("/dev/null",O_RDWR);
-
fd1=dup(fd0);
-
fd2=dup(fd0);
-
//initialize the log file
-
openlog(cmd,LOG_CONS,LOG_USER);
-
if(fd0!=0||fd1!=1||fd2!=2){
-
syslog(LOG_ERR,"unexpected file discriptors %d %d %d",fd0,fd1,fd2);
-
exit(0);
-
}
-
}
上述代码中一开始我用的return代替的exit,但是后来发现程序居然在前台,后来才意识到return只是返回到调用函数,而不是退出进程。
阅读(531) | 评论(0) | 转发(0) |