守护进程
5.1 概念
(1)什么是守护进程
Daemon(守护进程)是运行在后台的一种特殊进程。**它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。**它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。
(2)为什么需要守护进程
守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。
(3)守护进程实例
常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。
5.2 模型
(1)守护进程编程步骤
a.创建子进程,父进程退出,一切工作在子进程中执行,形式上脱离了控制终端 b.在子进程中创建新的会话(会话后面章节会提到),使子进程完全独立出来,脱离控制 c.改变当前目录为根目录,防止占用其他可卸载的文件系统 d.重设文件权限掩码,防止继承的文件创建屏蔽字拒绝某些权限,增加守护进程的灵活性 e.关闭文件描述符 f.守护进程退出处理
代码模型:
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
static bool flag = true;
void create_daemon();
void handler(int);
int main()
{
time_t t;
int fd;
create_daemon(); //进
struct sigaction act;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
// 函数执行开始
if(sigaction(SIGQUIT, &act, NULL))
{
printf("sigaction error.n");
exit(0);
}
while(flag)
{
fd = open("/home/mick/daemon.log", O_WRONLY | O_CREAT | O_APPEND, 0644);
if(fd == -1)
{
printf("open errorn");
}
t = time(0);
char *buf = asctime(localtime(&t));
write(fd, buf, strlen(buf));
close(fd);
sleep(60);
}
return 0;
}
void handler(int sig)
{
printf("I got a signal %dnI'm quitting.n", sig);
flag = false;
}
void create_daemon()
{
pid_t pid;
pid = fork(); //创建子进程
if(pid == -1)
{
printf("fork errorn");
exit(1);
}
else if(pid) //关闭父进程
{
exit(0);
}
if(-1 == setsid()) //在子进程中创建新的会话
{
printf("setsid errorn");
exit(1);
}
pid = fork(); //再次分离,更加稳定
if(pid == -1)
{
printf("fork errorn");
exit(1);
}
else if(pid)
{
exit(0);
}
chdir("/"); //改变当前目录为根目录
int i;
for(i = 0; i < 3; ++i)
{
close(i); //关闭原始三个流
//反正也失去了控制终端,再留着这三个也没意义
}
umask(0); //重设文件掩码
return;
}
注意守护进程一般需要在 root 权限下运行。
通过
ps -ef | grep ‘daemon’
如果想退出守护进程,kill -9 就好
其实,上面那套还有更直接的,直接通过库函数来创建守护进程:
#include <unistd.h>
int daemon(int nochdir, int noclose);
然后这个是官方解释,反正我看得懂 If nochdir is zero, daemon() changes the process’s current working directory to the root directory ("/"); otherwise, the current working directory is left unchanged.
If noclose is zero, daemon() redirects standard input, standard
output and standard error to /dev/null; otherwise, no changes are
made to these file descriptors.
然后我们对上面那串代码简化一下:
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
static bool flag = true;
void handler(int);
int main()
{
time_t t;
int fd;
if(-1 == daemon(0, 0))
{
printf("daemon errorn");
exit(1);
}
struct sigaction act;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if(sigaction(SIGQUIT, &act, NULL))
{
printf("sigaction error.n");
exit(0);
}
while(flag)
{
fd = open("/home/mick/daemon.log", O_WRONLY | O_CREAT | O_APPEND, 0644);
if(fd == -1)
{
printf("open errorn");
}
t = time(0);
char *buf = asctime(localtime(&t));
write(fd, buf, strlen(buf));
close(fd);
sleep(60);
}
return 0;
}
void handler(int sig)
{
printf("I got a signal %dnI'm quitting.n", sig);
flag = false;
}
其实就是用库函数替换掉我们自己的函数。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP中检查isset()和!empty()函数的必要性
- python代码中怎么换行
- PHP让网站移动访问更加友好方法
- python代码区分大小写吗
- php面试中关于面向对象的相关问题
- python实现在线翻译
- Python字符串格式化常用手段及注意事项
- PHP count_chars()函数讲解
- 浅谈keras使用中val_acc和acc值不同步的思考
- PHP安装BCMath扩展的方法
- keras实现多GPU或指定GPU的使用介绍
- 浅谈keras中的keras.utils.to_categorical用法
- python 使用多线程创建一个Buffer缓存器的实现思路
- keras.utils.to_categorical和one hot格式解析
- Python OpenCV读取中文路径图像的方法