文档章节

守护进程daemon详解

 随性_
发布于 2016/07/15 11:21
字数 2031
阅读 269
收藏 6

一:守护进程概述

Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。

二:创建守护进程步骤:

首先我们要了解一些基本概念:

  • 每个进程属于一个进程组
  • 每个进程组有组号和组长,组长进程的pid就是该进程组的组号(pgid)
  • 一个进程只能为它自己或子进程设置进程组ID号

会话期:

会话期(session)是一个或多个进程组的集合,当集合中只有一个进程组时,sid与该进程组 组长的pid相同,这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端,控制终端,登录会话和进程组通常是从父进程继承下来的。

setsid()函数可以建立一个对话期:

 如果,调用setsid的进程不是一个进程组的组长,此函数创建一个新的会话期;如果是该进程组的组长,则此函数返回错误

(1)此进程变成该对话期的首进程

(2)此进程变成一个新进程组的组长进程

(3)此进程没有控制终端,如果在调用setsid前,该进程有控制终端,那么与该终端的联系被解除

(4)为了保证这一点,我们先调用fork()然后exit(),此时只有子进程在运行,fork后的子进程pid是重新分配的,即保证了此时运行的进程永远不会是进程组的组长

现在我们来给出创建守护进程所需步骤:

编写守护进程的一般步骤步骤:

(1)在父进程中执行fork并exit推出;

(2)在子进程中调用setsid函数创建新的会话;

(3)在子进程中调用chdir函数,让根目录 ”/” 成为子进程的工作目录;

(4)在子进程中调用umask函数,设置进程的umask为0;

(5)在子进程中关闭任何不需要的文件描述符

以图解两次fork的过程:

前提,会话中只有一个进程组,进程组中只有一个进程;

pid ppid pgid(组id) sid(session id) 组长(y/n)
100 10 100 100 y

第一次fork时:

pid ppid pgid(组id) sid(session id) 组长(y/n)
100 10 100 100 y
101 100 100(extends parent) 100 n

exit父进程:

pid ppid pgid(组id) sid(session id) 组长(y/n)
101 100 100 100 n

init进程接管:

pid ppid pgid(组id) sid(session id) 组长(y/n)
101 1 100 100 n

执行setsid后:

pid ppid pgid(组id) sid(session id) 组长(y/n)
101 1 101 101 y

第二次fork:

pid ppid pgid(组id) sid(session id) 组长(y/n)
101 1 101 101 y
102 101 101 101 n

exit父进程:

pid ppid pgid(组id) sid(session id) 组长(y/n)
102 101 101 101 n

由init进程接管:

pid ppid pgid(组id) sid(session id) 组长(y/n)
102 1 101 101 n

三:守护进程的编写步骤

  1. fork子进程,而后父进程退出,此时子进程会被init进程接管
  2. 修改子进程的工作目录、创建新进程组和新会话、修改umask
  3. 子进程再次fork一个进程,这个进程可以称为孙子进程,而后子进程退出,此时子进程会被init进程接管
  4. 重定向孙子进程的标准输入流、标准输出流、标准错误流到/dev/null。

完成上面的4个步骤,那么最终的孙子进程就称为守护进程。先看下代码,后面再分析下每个步骤的原因。

#!/usr/bin/env python

#coding=utf8

import os, sys, time

#产生子进程,而后父进程退出

pid = os.fork()

if pid > 0:

  sys.exit(0)


#修改子进程工作目录

os.chdir("/")

#创建新的会话,子进程成为会话的首进程

os.setsid()

#修改工作目录的umask

os.umask(0)

#创建孙子进程,而后子进程退出

pid = os.fork()

if pid > 0:

  sys.exit(0)


#重定向标准输入流、标准输出流、标准错误

sys.stdout.flush()

sys.stderr.flush()

si = file("/dev/null", 'r')

so = file("/dev/null", 'a+')

se = file("/dev/null", 'a+', 0)

os.dup2(si.fileno(), sys.stdin.fileno())

os.dup2(so.fileno(), sys.stdout.fileno())

os.dup2(se.fileno(), sys.stderr.fileno())



#孙子进程的程序内容

while True:

    time.sleep(10)

    f = open('/home/test.txt', 'a')

    f.write('hello')

上面的程序没有任何错误处理,但是不影响原理分析。如果要应用到项目里,还需完善。下面笔者谈下自己对每个步骤的理解。

1、fork子进程,父进程退出

通常,我们执行服务端程序的时候都会通过终端连接到服务器,成功连接后会加载shell环境,终端和shell都是进程,shell进程是终端进程的子进程,通过ps命令可以很容易的查看到。在这个shell环境下一开始执行的程序都是shell进程的子进程,自然会受到shell进程的影响。在程序里fork子进程后,父进程退出,对了shell进程来说,这个父进程就算执行完了,而产生的子进程会被init进程接管,从而也就脱离了终端的控制。

2、关闭打开的文件描述符和修改子进程的工作目录

进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误,子进程在创建的时候会继承父进程的工作目录,如果执行的程序是在u盘里的,就会导致u盘不能卸载。

3、创建新会话

使用setsid后,子进程就会成为新会话的首进程(session leader);子进程会成为新进程组的组长进程;子进程没有控制终端。

4、修改umask

由于umask会屏蔽权限,所以设定为0,这样可以避免读写文件时碰到权限问题。

5、fork孙子进程,子进程退出

经过上面几个步骤后,子进程会成为新的进程组老大,可以重新申请打开终端,为了避免这个问题,fork孙子进程出来。

6、重定向孙子进程的标准输入流、标准输出流、标准错误流到/dev/null

因为是守护进程,本身已经脱离了终端,那么标准输入流、标准输出流、标准错误流就没有什么意义了。所以都转向到/dev/null,就是都丢弃的意思。

7. 处理SIGCHLD信号 
处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。 
signal(SIGCHLD,SIG_IGN); 

参考资料:

http://www.01happy.com/linux-python-daemon/

http://www.cnblogs.com/mickole/p/3188321.html

http://blog.csdn.net/jason314/article/details/5640969


针对守护这个概念延伸到python,python也有守护线程的概念

python daemon理解:
    守护进程只与主进程有相互作用关系;主线程结束为前提,守护进程保证所有的子线程都执行完后就全部退出,即使守护进程没有执行完进程也会退出;

参考资料:

http://www.dongwm.com/archives/guanyuthreadingyanjiuer/

© 著作权归作者所有

共有 人打赏支持
粉丝 9
博文 16
码字总数 18722
作品 0
南昌
私信 提问
supervisor安装和配置指南

supervisor:是用python写的一个进程管理工具,用来启动,重启,关闭进程。 注意:Supervisor只能管理非daemon的进程,也就是说Supervisor不能管理守护进程。否则提示Exited too quickly (p...

高运维之路
05/03
0
0
[转] chcon 命令详解

chcon命令:修改对象(文件)的安全上下文。比如:用户:角色:类型:安全级别。 命令格式: Chcon [OPTIONS…] CONTEXT FILES….. Chcon [OPTIONS…] –reference=PEF_FILES FILES… 说明:...

鉴客
2012/09/18
860
0
Linux 进程管理与监控(supervisor and monit)

一、Supervisor 1、安装 宿主机环境:( Centos 6.5 ) pip2.7 install supervisor 2、创建配置文件 通过 echosupervisordconf 命令来创建配置文件: echosupervisordconf >/etc/supervisord.co......

qw87112
06/28
0
0
Linux 守护进程

一、基本概念 守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊...

吃一堑消化不良
2016/12/09
17
0
Unix环境高级编程笔记 :13、守护进程

1 守护进程 守护进程也称精灵进程(daemon)是生存期较长的一种进程。它们常常在系统自举时启动,仅在系统关闭时才终止。 因为没的控制终端,所以它们是在后台运行的。 2、守护进程特征 父进程...

活的很快乐
2013/11/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

React和Redux的连接react-redux

通过Redux文档来了解react-redux,在一段时间的实践后准备翻一翻源代码,顺便做些相关的总结。我看的代码的npm版本为v4.0.0,也就是说使用的React版本是0.14.x。 react-redux提供两个关键模块...

前端攻城老湿
24分钟前
0
0
1、Mybatis连接池Context.xml配置

注意: (1)mybatis 3.2 之前 通过 set get 方法 获取相关属性。之后通过属性姓名获取相关关联。 (2)mybatis 映射 优先为 sql 语句中的别名与实体类的属性进行映射。 (3)jndi Java用于调...

KingFightingAn
40分钟前
0
0
Android 界面漩涡扭曲动效实现

背景:之前偶然看到优酷有类似的页面切换动画效果。于是自己也打算来实现下这样的效果。 动效说明:点击界面中的任意位置,界面以点击位置作为中心点,开始以漩涡状态,扭曲,收缩。直到消失...

Carlyle_Lee
50分钟前
2
0
聊聊我怎么系统学习Linux技能并快速提高的

聊聊我怎么系统学习Linux技能并快速提高的 随着电子信息科技时代的发展,学会使用计算机在我们的生活中成为了必不可少的一项技能。而作为计算机中的三大操作系统之一的Linux更是饱受计算机爱...

linuxCool
今天
4
0
Android/Java 获取一个byte[]的真实编码,用于解决乱码问题

来源地址:https://blog.csdn.net/qq_31384551/article/details/81627840 一个byte数组,byte[] buf,是由一个字符串转换来的,如何判断字符串使用的是什么编码? Mozilla的一个组件提供了相应...

她叫我小渝
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部