本文介绍一个例程daemon_init()

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <syslog.h>
#define MAXFD 64
void daemon_init(const char *pname, int facility)
{
int i:
pid_t pid;
/* fork,终止父进程 */
if (pid = fork())
exit(0);
/* 第一子进程 */
setsid();
signal(SIGHUP,SIG_IGN);
/* fork,终止第一子进程 */
if (pid = fork())
exit(0);
/* 第二子进程 */
daemon_proc = 1;
/* 将工作目录设定为"/" */
chdir("/");
/* 清除文件掩码 */
umask(0);
/* 关闭所有文件句柄 */
for (i = 0;i < MAXFD;i++)
{
close(i);
}
/* 打开log */
openlog(pname,LOG_PID,facility);
}

  守护进程建立的主要过程

1、fork

通过fork出一个子进程,并把父进程关闭,这样子进程就成了后台进程,而且子进程从父进程那里继承了组标识符同时又拥有了自己的进程标识符,这样就保证了子进程不会是一个进程组的首进程

2、setsid

setsid()创建了一个新的进程组,调用进程成为了这个进程组的首进程,这样就使得该进程脱离了原来的终端,成为了独立于终端外的进程

3、忽略SIGHUP信号,重新fork

这样使进程不再是进程组的首进程,可以放置在某些情况下的打开终端而重新与终端发生联系

4、改变工作目录,清除文件掩码

改变目录是为了切断进程与原有文件系统的联系,并且保证无论从什么地方启动进程都能正常工作,清除文件掩码是为了消除进程自身对其创建文件的影响

5、关闭全部已经打开的文件jubing

防止子进程继承了父进程中打开的文件而使这些文件始终保持打开状态从而产生某些冲突

6、打开log系统

个人对这个例子的理解就是,首先该进程是一个父进程,拥有进程组标识符和进程标识符,然后通过fork创建一个子进程(第一子进程),终止父进程,但是呢,子进程虽然拥有自己的进程标识符,但却继承了父进程的进程组(进程组一)标识符,所以,该进程组是原先就存在的,那么这个第一子进程就不是该进程组的首进程了。然后呢,通过setsid创建了一个新的进程组(进程组二),因为是新创建的,所以必然是首进程咯,那么这个首进程就脱离了原先的进程环境,独立于终端外了,然后呢,在这个新的进程组(进程组二)又重新fork出一个子进程(第二子进程),对于第二子进程来说,第一子进程就是其父进程,所以将父进程终止就是将第一子进程终止,此时,第二子进程已经独立于原来的终端外了,并且该第二子进程也不是所属进程组(进程组二)的首进程,最后改变工作目录,清掩码,关闭文件句柄,打开Log系统,那么这个第二子进程就是创建的守护进程,嗯,我是这么理解的,不知道理解对不对?请大神指出!

Linux网络编程学习(四) -----守护进程的建立(第三章)的更多相关文章

  1. Linux网络编程学习计划

    由于网络编程是很重要的一块,自己这一块也比较欠缺,只知道一些皮毛,从今天开始系统学习<Linux网络编程>一书,全书分为十四个章节: 第一章   概论   P1-16 第二章   UNIX ...

  2. Linux网络编程学习路线

    转载自:https://blog.csdn.net/lianghe_work/article 一.网络应用层编程   1.Linux网络编程01——网络协议入门 2.Linux网络编程02——无连接和 ...

  3. Linux网络编程学习(二) ----- 进程控制(第三章)

    1.进程和程序 程序是一个可执行文件,而一个进程是一个执行中的程序实例.一个进程对应于一个程序的执行,进程是动态的,程序是静态的,多个进程可以并发执行同一个程序.比如几个用户可以同时运行一个编辑程序, ...

  4. Unix环境高级编程(十四)守护进程实现时间服务器

    守护进程是在后台运行不受终端控制的进程(如输入.输出等),一般的网络服务都是以守护进程的方式运行.守护进程脱离终端的主要原因有两点:(1)用来启动守护进程的终端在启动守护进程之后,需要执行其他任务.( ...

  5. Linux网络编程学习(一) ----- 概论和Linux模型(第一章第二章)

    1.什么是计算机网络,通信方式是什么? 计算机网络就是通过通信线路相互连接的计算机的集合,主要通过双绞线.同轴电缆.电话线或者光缆等有形传输介质通信,还有就是通过激光.微波.卫星等实现无线通信 2.W ...

  6. Linux网络编程学习(九) ----- 消息队列(第四章)

    1.System V IPC System V中引入的几种新的进程间通信方式,消息队列,信号量和共享内存,统称为System V IPC,其具体实例在内核中是以对象的形式出现的,称为IPC 对象,每个 ...

  7. Linux网络编程学习(七) ----- 有名管道(第四章)

    1.什么是有名管道?为什么有了管道还需要有名管道? 有名管道是解决管道不能提供非父子进程间通信的缺陷.管道在Linux系统内部是以文件节点(inode)的形式存在,但由于其对外的不可见性(“无名”性) ...

  8. Linux网络编程学习(五) ----- 信号(第四章)

    1.基本概念 进程阻塞: 进程执行条件得不到满足,就自动放弃CPU资源而进入休眠状态,以等待条件满足,当条件满足时,系统就将控制权还给该进程进行未完成的操作 共享资源: 进程间协调使用的系统资源 锁定 ...

  9. Linux网络编程学习(八) ----- 文件和记录锁定(第四章)

    1.什么是文件和记录锁定? 文件锁定的是整个文件,而记录锁定只锁定文件的一部分,文件和记录锁分为咨询式锁定和强制锁定 1)咨询式锁定 某个进程对某个文件进行了咨询式锁定,其他想访问该文件的进程将会被操 ...

随机推荐

  1. Locust 参数化

    概述: 和Loadrunner一样对于多用户并发时,重复登入或者数据的重复使用会造成脚本的失败,那么我们引入Loadrunner的参数化概念,对用户数据进行参数化来使脚本运行成功. 头绪:   use ...

  2. 构建gulp项目

    express是node.js中的构建工具,如果需要使用express构建,首先需要安装express. 构建一个项目: |-- app| |-- css| |-- js| | `-- class| ...

  3. jQuery-3.事件篇---表单事件

    jQuery表单事件之blur与focus事件 在之前2.8与2.9节我们学过了表单处理事件focusin事件与focusout事件,同样用于处理表单焦点的事件还有blur与focus事件 它们之间的 ...

  4. python3 基础整理

    基础语法 1.python中区分大小写 2.查看关键字用 import keyword print (keyword.kwlist) 3.注释 #  单行注释,多行注释的快捷键是ctr+/,取消注释的 ...

  5. spring--多人开发,模块化配置

    需要在配置文件中配置: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="h ...

  6. 【DB2】SQL1585N 由于没有具有兼容页面大小的可用系统临时表空间,因此无法创建临时表。SQLSTATE=54048

    自己写了一段SQL,SQL中包含ORDER BY 字句,但是在执行的时候报错如下: 经过查询发现是由于临时表空间的PAGESIZE不够大,可考虑建16k或者32k PAGESIZE的表空间 示例如下: ...

  7. Python生成器(generator)和迭代器(Iterator)

    列表生成式 a = [i+1 for i in range(10)] print(a) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 这就是列表生成式 生成器(generator) ...

  8. 我发起了一个 .Net 开源 跨平台 GUI (界面开发框架)项目 HtmlCore

    大家好 , 我发起了一个 .Net 开源 跨平台 GUI (界面开发框架)项目 , 名字叫 HtmlCore  . 项目的一个主要目标是可以用 .Net 在 移动设备 上 开发 GUI 程序 (界面程 ...

  9. .net 连接 Oracle 可能需要配置

    D:\Program Files (x86)\Oracle Developer Tools for VS2013\network\admin\tnsnames.ora

  10. MySQL视图-(视图创建,修改,删除,查看,更新数据)

    视图是一种虚拟存在的表,对于使用视图的用户来说基本上是透明的.视图并不在数据库中实际存在,行和列数据来自定义视图的查询总使用的表,并且是在使用视图时动态生成的. 视图相对于普通表的优势: 简单:使用视 ...