守护进程
守护进程也称Daemon(精灵)进程,是Linux中的后台服务进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。一般采用以d结尾的名字。如httpd,nfsd、sshd等
Linux后台的一些系统服务进程,没有控制终端,不能直接和用户交互。不受用户登录、注销的影响,一直在运行着,它们都是守护进程。如:预读入缓输出机制的实现;ftp服务器;nfs服务器等
创建守护进程,最关键的一步是调用setsid函数创建出来一个新的session,并成为session leader
创建守护进程模型:
1、创建子进程,父进程退出
所有工作在子进程中进行形式上脱离了控制终端
2、在子进程中创建会话
setsid()函数
使子进程完全独立出来,脱离控制
3、改变当前目录位置
chdir()函数
防止占用可卸载的文件系统
也可以换成其他路径
4、重设文件权限掩码
umask()函数
防止继承的文件创建屏蔽字拒绝某些权限
增加守护进程灵活性
5、关闭/重定向文件描述符
继承的打开文件不会用到,浪费系统资源,无法卸载
6、开始执行守护进程核心工作守护进程退出处理程序模型,while()
守护进程demo:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <time.h> void daemonize() { pid_t pid; // 创建子进程,并结束父进程 pid = fork(); if (pid < 0) { perror("fork"); exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } // 创建新会话 if (setsid() < 0) { perror("setsid"); exit(EXIT_FAILURE); } // 修改当前工作目录 if (chdir("/") < 0) { perror("chdir"); exit(EXIT_FAILURE); } // 设置umask umask(0); // 关闭标准输入、输出、错误流,并重定向到/dev/null close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); open("/dev/null", O_RDWR); // stdin dup2(0, STDOUT_FILENO); // stdout dup2(0, STDERR_FILENO); // stderr } void main_loop() { FILE *log_file; time_t current_time; // 打开日志文件 log_file = fopen("/tmp/daemon.log", "a+"); if (log_file == NULL) { perror("fopen"); exit(EXIT_FAILURE); } // 每隔一段时间向日志文件中写入消息 while (1) { time(¤t_time); fprintf(log_file, "Daemon is running... %s", ctime(¤t_time)); fflush(log_file); sleep(10); // 10秒 } fclose(log_file); } int main() { // 创建守护进程 daemonize(); // 进入主循环 main_loop(); return 0; }
执行结果:
daemon守护进程会在后台运行,可以在/tmp/daemon.log中获取到相应的log信息: