题目
创建一个守护进程 ,使用 Linux 信号机制,让守护进程退出。
代码
/************************************************************************* > File Name: main.c > Author: 杨永利 > Mail: 1795018360@qq.com > Created Time: 2021年07月16日 星期五 18时38分59秒 ************************************************************************/ #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #define MAXFILE 3 // 创建守护进程 void init_daemon(void) { pid_t pid = 0; int i = 0; // 第一次 fork,使之成为守护进程 pid = fork(); if (pid < 0) { // 判断返回值,fork 函数出错 perror("fork error."); exit(1); } else if (pid > 0) { // 父进程,退出 exit(0); } // 子进程 // 使子进程成为新的会话组长和进程组长,摆脱原会话控制,,摆脱原进程组控制, 摆脱控制终端控制 setsid(); // 改变工作目录,防止其他原因 ,导致工作目录不存在 // 第二次 fork, pid = fork(); if (pid < 0) { // 判断返回值,fork 函数出错 perror("fork error."); exit(1); } else if (pid > 0) { // 父进程,退出 exit(0); } //关闭打开的文件描述符,避免资源浪费 for (i = 0; i < MAXFILE; ++i) { // close(i); } chdir("/"); // 重设文件权限掩码 umask(0); return; } void mysighandler_t(int arg) { printf("收到信号 SIGUSR1 系统开始退出 \n"); exit(1); } int main(int argc, char const *argv[]) { // 注册一个信号 : 告诉 linux 内核 当有信号 SIGUSR1 发给我的时候 , 请你调用这个 apimysighandler_t signal(SIGUSR1, mysighandler_t); //创建守护进程 init_daemon(); printf("守护进程启动...\n"); while (1) { sleep(5); printf("程序正在后台运行...\n"); } return 0; }
知识回顾
守护进程
守护进程概念
守护进程:Daemon(精灵)进程,是 Linux 中的后台服务进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。一般采用以 d 结尾的名字。
创建守护进程模型
- 创建子进程,父进程退出
所有工作在子进程中进行形式上脱离了控制终端。
- 在子进程中创建新会话
setsid()函数,使子进程完全独立出来,脱离控制。
- 改变当前目录为根目录
chdir()函数,防止占用可卸载的文件系统,也可以换成其它路径。
- 重设文件权限掩码
umask()函数,防止继承的文件创建屏蔽字拒绝某些权限,增加守护进程灵活性。
- 关闭文件描述符
继承的打开文件不会用到,浪费系统资源,无法卸载。
- 开始执行守护进程核心工作
- 守护进程退出处理程序模型
信号
信号:是进程间通信(IPC)方式之一。
信号机制
A 给 B 发送信号,B 收到信号之前执行自己的代码,收到信号后,不管执行到程序的什么位置,都要暂停运行,去处理信号,处理完毕再继续执行。与硬件中断类似——异步模式。但信号是软件层面上实现的中断,早期常被称为“软中断”。
每个进程收到的所有信号,都是由内核负责发送的。