多进程编程之守护进程Daemonize
1、守护进程
守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。所有的守护进程都没有控制终端,其终端名设置为问号。
2、编程规则
1)首先调用umask函数将文件模式创建屏蔽字设置为一个已知值,通常是0;
umask函数为进程设置文件模式创建屏蔽字,并返回以前的值。umask也是shell命令,功能和umask函数一样。
#include <sys/stat.h> mode_t umask(mode_t mask);
在进程创建一个新的文件或目录时,如调用open函数创建一个新文件,新文件的实际存取权限是mode与umask按照 mode&~umask运算以后的结果。umask函数用来修改进程的umask。
首先看一下umask命令的作用:
首先查看一下当前的umask为022,用vi创建一个umask_3.c,查看该文件的权限为644,修改umask为0,vi创建umask_4.c,查看该文件的权限为666。
umask函数的使用:
实现函数,首先修改当前进程umask为0.创建fan_test1文件,然后修改umask为006,创建文件fan_test2,输出结果如下图
#include <stdio.h>
#include <sys/stat.h> int main()
{
umask();
if (creat("fan_test1",S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) < )
printf("error creat\n");
umask(S_IROTH|S_IWOTH);
if (creat("fan_test2",S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) < )
printf("error creat\n");
return ;
}
2)调用fork,然后是父进程exit。创建守护进程最关键的一步是调用setsid函数创建一个新的会话(会话是一个或多个进程组的集合),使守护进程成为新会话的首进程,并成为新进程组的组长,失去当前的控制终端,成为一个没有控制终端的进程。而调用函数setsid()之前,要保证当前进程不是进程组的组长,否则该函数返回-1;要保证当前进程不是进程组的组长,就要调用fork,父进程退出;fork创建的子进程和父进程在同一个进程组中,进程组的组长必然是该组的第一个进程,所以子进程不可能是该组的第一个进程,fork之后调用setsid就没有问题了;
3)调用setsid()函数创建一个新的会话:
4)将当前的工作目录更改为根目录。如果守护进程所在的目录为一个挂载的文件系统,那么该文件系统就不能被卸载;另外如果守护进程所在的目录不是根目录,启动守护进程之后,当前工作目录所在的文件夹将不能删除;调用函数chdir("/");
5)关闭打开的文件描述符;子进程有可能从父进程继承了一些打开的文件,这些文件可能守护进程将不再使用,但这些文件描述符依然消耗系统资源,也有可能导致相关的文件系统无法被卸载。
关闭文件描述符的方法:
方法1:
#include <sys/resource.h> struct rlimit rl; 6 if(getrlimit(RLIMIT_NOFILE, &rl) < )
7 {
perror("getrlimit(RLIMIT_NOFILE, &rl)");
return -;
10 }
11 if(rl.rlim_max == RLIM_INFINITY)
12 {
13 rl.rlim_max = ;
14 }
15 for(i = ; i < rlim_max; i++)
{
close(i);
}
方法2:
max_fd = sysconf(_SC_OPEN_MAX);
for(i = ; i < max_fd; i++)
{
close(i);
}
6)守护进程打开/dev/null使其具有文件描述符0、1和2,也就是将0、1、2的文件描述符都指向/dev/null;
/*attach file descriptions 0,1 and 2 to /dev/null*/
fd0 = open("/dev/null", O_RDWR);
fd1 = dup();
fd2 = dup();
为什么会有这一步操作,守护进程已经脱离终端了,为什么还要将文件描述符0、1、2重定向到/dev/null呢,并且前面已经有了关闭所有文件描述符的操作,文件描述符已经关闭了,在此处为什么还要再打开,两者不是冲突了么?
7)再次调用fork,使父进程退出;第一次fork()后的子进程已经成为会话组的组长,有权利再调出一个终端,如果出现此情况,则未达到完全脱离终端的目的,此时再调用fork并退出父进程,使得此时的子进程成为完全的后台进程,独立于任何的终端,在第二次fork之前通常会忽略SIGHUP信号,这是因为会话首进程退出时会给该会话中的前台进程组(当打开控制终端后,就有一个前台进程组)的所有进程发送SIGHUP信号,而信号的默认处理函数通常是进程终止,因此需要对信号进程屏蔽处理;
实现一个守护进程:
#include <stdio.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdlib.h>
void daemonize(void)
{
struct rlimit rl;
pid_t pid;
struct sigaction sa;
int i;
umask();
if (getrlimit(RLIMIT_NOFILE, &rl) < ) {
printf("error getrlimit\n");
exit();
}
if ((pid = fork()) < ) {
printf("error fork\n");
exit();
} else if (pid != ) {
exit();
}
setsid();
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = ;
if (sigaction(SIGHUP, &sa, NULL) < ) {
printf("error sigaction\n");
exit();
}
if (chdir("/") < ) {
printf("error chdir\n");
exit();
}
if (rl.rlim_max == RLIM_INFINITY)
rl.rlim_max = ;
for (i = ; i < rl.rlim_max; i++)
close(i); if ((pid = fork()) < ) {
printf("error fork\n");
exit();
} else if (pid != ) {
exit();
} } int main()
{
daemonize();
while() {
printf("111111111111111\n");
sleep();
} }
多进程编程之守护进程Daemonize的更多相关文章
- Unix环境高级编程(十三)守护进程
守护进程也称为精灵进程是一种生存期较长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.他们常常在系统引导装入时启动,在系统关闭时终止.unix系统有很多守护进程,大多数 ...
- python 之 并发编程(守护进程、互斥锁、IPC通信机制)
9.5 守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就立即终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic process ...
- Linux编程实现守护进程
Linux 守护程序 守护进程(Daemon)它是在一个特定的过程的背景进行.它独立于控制终端的和周期性地执行某些任务或待某些事件.是一种非常实用的进程. Linux的大多数server就是用守护进程 ...
- Unix环境高级编程:守护进程
参考 Unix环境高级编程,第9,13章 介绍 守护进程就是Linux中使用ps aux那些一般以d结尾的程序,比如rsyslogd,sshd等,为daemon简称.他们是长期在后台执行的随终端关闭而 ...
- 高级UNIX环境编程13 守护进程
linux下,keventd守护进程为内核中运行的执行的函数提供进程上下文 bdflush,kupdated将高速缓存中的数据冲洗到磁盘上
- Linux系统编程之--守护进程的创建和详解【转】
本文转载自:http://www.cnblogs.com/mickole/p/3188321.html 一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终 ...
- python并发编程之守护进程、互斥锁以及生产者和消费者模型
一.守护进程 主进程创建守护进程 守护进程其实就是'子进程' 一.守护进程内无法在开启子进程,否则会报错二.进程之间代码是相互独立的,主进程代码运行完毕,守护进程也会随机结束 守护进程简单实例: fr ...
- [linux] C语言Linux系统编程-做成守护进程
守护进程: 必须是init进程的子进程,运行在后台,不与任何控制终端相关联. 通过以下步骤成为守护进程 1.调用fork()创建出来一个新的进程,这个新进程会是将来的守护进程 2.在新守护进程的父进程 ...
- linux系统编程:守护进程详解及创建,daemon()使用
一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而且提供某种服务,不是对整个 ...
随机推荐
- zabbix3.4 监控路由器报错No Such Instance currently exists at this OID
zabbix 3.4 监控报错No Such Instance currently exists at this OID 1.首先查看监控的路由器的监控项是否报警 监控主机报错出现这个 No Such ...
- 【日常训练】Hockey(CodeForces-96C)
题意与分析 对于这题题意的理解比较重要,因为这是一条傻逼题: 大小写保持不变 原串中出现的非法字符串里的每一个字符都要替换 Lucky Letter越多越好 这样一种情况下,算法其实特别简单.我傻逼在 ...
- Linux日常积累
1. /etc/bashrc(有的 Linux 没有这个文件) 和 /etc/profile ,它们分别存放的是 shell 变量和环境变量,写在 /etc/profile 里面的是对所有用户永久 ...
- TPO-19 C1 Discussing A Point Raised In A Lecture
TPO-19 C1 Discussing A Point Raised In A Lecture 第 1 段 1.Listen to a conversation between a student ...
- Jmeter实战
Jmeter实战 入门篇 1.下载与使用 下载地址:http://jmeter.apache.org/download_jmeter.cgi 开源,基于java编写,所以得有jdk(jre)环境,下载 ...
- Annotation 使用备忘
title: Annotation 使用备忘 date: 2016-11-16 23:16:43 tags: [Annotation] categories: [Programming,Java] - ...
- more和less命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/aijianshi/p/5750911.html 一.more命令 more功能类似 cat ,cat命令是整个文件的内 ...
- RabbitMQ基础使用之集群构建
简介 RabbitMQ是基于Erlang开发的一种消息队列服务,本篇文章主要部署三台机器用来实现集群的普通模式与镜像模式!欢迎大家吐槽交流学习! 特点 集群节点包括内存节点和磁盘节点,有了磁盘节点就支 ...
- 小米6x抓包小程序https请求
1. charles安装证书,手机设置代理等这里不多讲了, 请进入下面链接查看详细 https://blog.csdn.net/manypeng/article/details/79475870 2. ...
- 记一次线上gc调优的过程
近期公司运营同学经常表示线上我们一个后台管理系统运行特别慢,而且经常出现504超时的情况.对于这种情况我们本能的认为可能是代码有性能问题,可能有死循环或者是数据库调用次数过多导致接口运行 ...