创建子进程,父进程退出
子进程中创建新会话
改变当前目录为根目
重设文件权限掩码
关闭文件描述符
同文件权限码一样,用fork函数新建的子进程会从父进程那里继承一些已经打开了的文件。
这些被打开的文件可能永远不会被守护进程读写,但它们一样消耗系统资源,而且可能导致所在的文件系统无法卸下。
在上面的第二步之后,守护进程已经与所属的控制终端失去了联系。
因此从终端输入的字符不可能达到守护进程,守护进程中用常规方法(如printf)输出的字符也不可能在终端上显示出来。所以,文件描述符为0、1和2 的3个文件(常说的输入、输出和报错)已经失去了存在的价值,也应被关闭。
for(i=0;i<MAXFILE;i++)
close(i);
守护进程退出处理
当用户需要外部停止守护进程运行时,往往会使用 kill命令停止该守护进程。
所以,守护进程中需要编码来实现kill发出的signal信号处理,达到进程的正常退出。
//守护进程的完整实例(每隔10s在/tmp/dameon.log中写入一句话)
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXFILE 65535
volatile sig_atomic_t _running = 1;
void sigterm_handler(int arg) {
_running = 0;
}
int main() {
pid_t pc, pid;
int i, fd, len;
char *buf = "this is a Dameon\n";
len = strlen(buf);
//第一步
pc = fork();
if(pc < 0) {
printf("error fork\n");
exit(1);
} else if(pc > 0) {
exit(0);
}
//第二步
setsid();
pid = fork();//与终端完全脱离[1]
if (pid < 0) {
perror("fork error");
} else if (pid > 0) {
exit(0);
}
//第三步
chdir("/");
//第四步
umask(0);
//第五步
for(i = 0;i < MAXFILE; i++) {
close(i);
}
signal(SIGTERM, sigterm_handler);
while( _running ) {
if((fd = open("/tmp/dameon.log", O_CREAT | O_WRONLY | O_APPEND, 0600)) < 0) {
perror("open");
exit(1);
}
write(fd, buf, len);
close(fd);
usleep(10 * 1000);//10毫秒
}
}