文档章节

守护进程daemon详解

 随性_
发布于 2016/07/15 11:21
字数 2031
阅读 226
收藏 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/

© 著作权归作者所有

共有 人打赏支持
粉丝 8
博文 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

没有更多内容

加载失败,请刷新页面

加载更多

20180920 rzsz传输文件、用户和用户组相关配置文件与管理

利用rz、sz实现Linux与Windows互传文件 [root@centos01 ~]# yum install -y lrzsz # 安装工具sz test.txt # 弹出对话框,传递到选择的路径下rz # 回车后,会从对话框中选择对应的文件传递...

野雪球
今天
0
0
OSChina 周四乱弹 —— 毒蛇当辣条

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ 达尔文:分享花澤香菜/前野智昭/小野大輔/井上喜久子的单曲《ミッション! 健?康?第?イチ》 《ミッション! 健?康?第?イチ》- 花澤香菜/前野智...

小小编辑
今天
6
2
java -jar运行内存设置

java -Xms64m #JVM启动时的初始堆大小 -Xmx128m #最大堆大小 -Xmn64m #年轻代的大小,其余的空间是老年代 -XX:MaxMetaspaceSize=128m # -XX:CompressedClassSpaceSize=6...

李玉长
今天
1
0
Spring | 手把手教你SSM最优雅的整合方式

HEY 本节主要内容为:基于Spring从0到1搭建一个web工程,适合初学者,Java初级开发者。欢迎与我交流。 MODULE 新建一个Maven工程。 不论你是什么工具,选这个就可以了,然后next,直至finis...

冯文议
今天
1
0
RxJS的另外四种实现方式(四)——性能最高的库(续)

接上一篇RxJS的另外四种实现方式(三)——性能最高的库 上一篇文章我展示了这个最高性能库的实现方法。下面我介绍一下这个性能提升的秘密。 首先,为了弄清楚Most库究竟为何如此快,我必须借...

一个灰
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部