守护进程是脱离终端并在后台运行的进程。守护进程脱离终端是为了避免进程在执行过程中的信息在任何终端上显示,并且进程也不会被任何终端所产生的中断信息打扰。
守护进程一般生存周期都很长。一般都是默默的在后台做一些事情,用户不会直接感受到它的存在。
创建守护进程的步骤
1 与终端脱离
创建子进程,父进程退出。
2 在子进程中创建新会话
意义在于:让守护进程独立
让进程摆脱原会话的控制
让进程摆脱原进程组的控制
让进程摆脱原控制终端的控制
那么,在创建守护进程时为什么要调用setsid函数呢?由于创建守护进程的第一步调用了fork函数来创建子进程,再将父进程退出。由于在调用了fork函数时,子进程全盘拷贝了父进程的会话期、进程组、控制终端等,虽然父进程退出了,但会话期、进程组、控制终端等并没有改变,因此,这还不是真正意义上的独立开来,而setsid函数能够使进程完全独立出来,从而摆脱其他进程的控制。setsid函数用于创建一个新会话,并成为该会话组的组长。
3 改变当前目录为根目录
释放目录
4 重设文件权限掩码
增强守护进程的灵活性
5 关闭文件描述符
释放资源
6 守护进程的退出处理
接收Kill信号,终止自己。
signal(SIGTERM, sigterm_handler);

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <signal.h> #include <string.h> #define MAXFILE 65535 int g_running; void sigterm_handler(int arg) { g_running = 0; } int main(int argc, char **argv) { pid_t pid; int i; int fd; printf("%s %d\n", argv[1], sizeof(argv[1])); pid = fork(); if (pid<0) { perror("first fork"); exit(1); } if (pid>0) //exit parent { exit(0); } else { setsid(); chdir("/"); umask(0); for (i=0; i<MAXFILE; i++) close(i); signal(SIGTERM, sigterm_handler); g_running = 1; while (g_running) { if ( (fd=open("/tmp/daemon.log", O_WRONLY | O_CREAT | O_APPEND, 0600)) < 0) { perror("open"); exit(1); } write(fd, argv[1], strlen(argv[1])); write(fd, "\n", 1); close(fd); sleep(5); } } return 1; }