http://blog.csdn.net/zg_hover/article/details/2553321

守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程。 Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。 同时,守护进程完成许多系统任务。比如,作业规划进程crond,打印进程lpd等。

.基本概念
.进程
.每个进程都有一个父进程
.当子进程终止时,父进程会得到通知并能取得子进程的退出状态。
.进程组
.每个进程也属于一个进程组
.每个进程主都有一个进程组号,该号等于该进程组组长的PID号
.一个进程只能为它自己或子进程设置进程组ID号
.会话期
.对话期(session)是一个或多个进程组的集合。
.setsid()函数可以建立一个对话期:
如果,调用setsid的进程不是一个进程组的组长,此函数创建一个新的会话期。
(1)此进程变成该对话期的首进程
(2)此进程变成一个新进程组的组长进程。
(3)此进程没有控制终端,如果在调用setsid前,该进程有控制终端,那么与该终端的联系被解除。
如果该进程是一个进程组的组长,此函数返回错误。
(4)为了保证这一点,我们先调用fork()然后exit(),此时只有子进程在运行,
子进程继承了父进程的进程组ID,但是进程PID却是新分配的,所以不可能是新会话的进程组的PID。
从而保证了这一点。 if((pid=fork())>0) //parent
exit(0);
else if(pid==0){ //th1 child
setsid(); //th1是成为会话期组长,使得与运行前的环境隔离开来
if(fork() ==0){ //th2不会是会话期组长(变成孤儿进程组)
...
}
}
一. 守护进程及其特性

    (1)守护进程最重要的特性是后台运行,即脱离控制终端。在这一点上DOS下的常驻内存程序TSR与之相似。
(2)其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符,控制终端,
会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)
中继承下来的。
(3)最后,守护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,
可以由作业规划进程crond启动,还可以由用户终端(通常是 shell)执行。
  总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。
因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。
二. 守护进程的编程要点  (来自UEAP)

  前面讲过,不同Unix环境下守护进程的编程规则并不一致。所幸的是守护进程的编程原则其实都一样,
区别在于具体的实现细节不同。这个原则就是要满足守护进程的特性。
同时,Linux是基于Syetem V的SVR4并遵循Posix标准,实现起来与BSD4相比更方便。编程要点如下; 1. 在后台运行。
  为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,
让Daemon在子进程中后台执行。 if(pid=fork())
exit(0); //是父进程,结束父进程,子进程继续 2. 脱离控制终端,登录会话和进程组
  进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。
这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。
控制终端,登录会话和进程组通常是从父进程继承下来的。
我们的目的就是要摆脱它们,使之不受它们的影响。
方法是在第1点的基础上,调用setsid()使进程成为会话组长: setsid();   说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。
setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。
由于会话过程对控制终端的独占性,进程同时与控制终端脱离。 3. 禁止进程重新打开控制终端
  现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。
可以通过使进程不再成为会话组长来禁止进程重新打开控制终端: if(pid=fork())
exit(0); //结束第一子进程,第二子进程继续(第二子进程不再是会话组长) 4. 关闭打开的文件描述符
  进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,
造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们: for(i=0;i 关闭打开的文件描述符close(i);> 5. 改变当前工作目录
  进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。
对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如 /tmpchdir("/") 6. 重设文件创建掩模
  进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。
为防止这一点,将文件创建掩模清除:umask(0); 7. 处理SIGCHLD信号
  处理SIGCHLD信号并不是必须的。
但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。
如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。
如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。
在Linux下可以简单地将 SIGCHLD信号的操作设为SIG_IGN。 signal(SIGCHLD,SIG_IGN);   这样,内核在子进程结束时不会产生僵尸进程。
这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。
void init_daemon(void)
{
int pid;
int i;
if((pid=fork())>)
exit();//退出父进程
else if(pid<)
exit();//fork失败
//是第一子进程,后台继续执行
setsid();//第一子进程成为新的会话组长和进程组长
//并与控制终端分离
if((pid=fork())>)
exit();//第一子进程退出
else if(pid<)
exit();//fork失败
//是第二子进程,继续
//第二子进程不再是会话组长 for(i=;i<NOFILE;i++)//关闭打开的文件描述符
close(i);
chdir("/tmp");//改变工作目录到/temp
umask();//重设文件创建掩码 return ;
}
												

【APUE】【转】守护进程编写的更多相关文章

  1. linux C守护进程编写

    linux编程-守护进程编写 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待 处理某些发生的事件.守护进程是一种很有用的进程. Linux的大多数服 ...

  2. Linux守护进程编写指南

    Linux守护进程编写指南 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种很有用的进 程.Linux的大多数服务器 ...

  3. linux守护进程编写实践

    主要参考:http://colding.bokee.com/5277082.html (实例程序是参考这的) http://wbwk2005.blog.51cto.com/2215231/400260 ...

  4. Linux守护进程编写方法及原理

    什么守护进程? 守护进程是运行在后台的一种用来提供服务的进程,他脱离控制台独立运行,守护进程是一种很有用的进 程. Linux的大多数服务器就是用守护进程实现的.比如,Internet服务器inetd ...

  5. 拾遗:Unix 守护进程编写规范

    //标准库自带函数,通常以 daemon(0, 0) 方式调用 int daemon(int nochdir, int noclose) Linux: #include <unistd.h> ...

  6. supervisor运行golang守护进程

    最近在鼓捣golang守护进程的实现,无意发现了supervisor这个有意思的东西.supervisor是一个unix的系统进程管理软件,可以用它来管理apache.nginx等服务,若服务挂了可以 ...

  7. Unix守护进程

    问题描述:         Unix守护进程 问题解决:     Unix守护进程没有控制终端,终端名设置为问号(?),终端前台进程组ID设置(TPGID)为-1 守护进程编写规则:      (1) ...

  8. 【转】学习Linux守护进程详细笔记

    [原文]https://www.toutiao.com/i6566814959966093837/ Linux守护进程 一. 守护进程概述 守护进程,也就是通常所说的Daemon进程,是Linux中的 ...

  9. 经典C/S服务器模型之守护进程

    linux编程-守护进程编写 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种很有用的进程. Linux的大多数服务 ...

随机推荐

  1. MySQL存储过程实现分页及变量的定义

    delimiter是MySQL中的命令,这个命令与存储过程没什么关系. 其实就是告诉mysql解释器,该段命令是否已经结束了,mysql是否可以执行了. 即改变输入结束符. 默认情况下,delimit ...

  2. ES6 export default 和 export 的区别

    export default 和 export 区别: 1.export与export default均可用于导出常量.函数.文件.模块等 2.你可以在其它文件或模块中通过import+(常量 | 函 ...

  3. MFC_综述

    第一天(win消息机制.SDK编程基础)    1.基本概念介绍(SDK.API.句柄.消息队列.winmain函数)    2.第一个Windows界面程序(winAPI)    3.消息循环和窗口 ...

  4. python基础知识12-异常

    几个命令: sudo apt install tree tree 当前目录以树形结构展示出来. tree a 查看a内的所有目录.也可以跟绝对路径. a = input('请输入您的密码') 将用户输 ...

  5. 剑指Offer(书):实现单例模式

    题目:设计一个类,我们只能生成该类的一个实例. 生成一个单例模式,有下列几种常用解法. 1.双重检查锁. 当运行在多线程环境中,此方法可以正常实现单例模式. public class Singleto ...

  6. 【BZOJ 1076】[SCOI2008]奖励关(期望)

    Description 你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物, 每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的 ...

  7. 数据结构实验7:实现二分查找、二叉排序(查找)树和AVL树

    实验7 学号:      姓名:     专业: 7.1实验目的 (1) 掌握顺序表的查找方法,尤其是二分查找方法. (2) 掌握二叉排序树的建立及查找. 查找是软件设计中的最常用的运算,查找所涉及到 ...

  8. PHP 小方法之 获取中文字的首字母

    public function getFirstCharter($str) { if (empty($str)) { return ''; } $fchar = ord($str{0}); if ($ ...

  9. python基础——3(流程控制)

    一.if判断 1.语法一: if 条件: 子代码块 示例代码: sex = 'female' age = 18 is_beautiful = True if sex == 'female' and a ...

  10. Haproxy的安装与配置

    一.Haproxy概念 Haproxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案.Haproxy特别适用于那些负载特大的web站点,这 ...