Linux系统编程——Daemon进程
目录
- Daemon进程介绍
- 前提知识
- Daemon进程的编程规则
Daemon进程介绍
Daemon运行在后台也称作“后台服务进程”。 它是没有控制终端与之相连的进程。它独立与控制终端、会话周期的执行某种任务。
那么为什么守护进程要脱离终端后台运行呢?
- 守护进程脱离终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的任何终端信息所打断。
那么为什么要引入守护进程呢?
- 由于在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依赖这个终端,这个终端就称为这些进程的控制终端。当控制终端被关闭时,相应的进程都会自动关闭。但是守护进程却能突破这种限制,它被执行开始运转,直到整个系统关闭时才退出。
几乎所有的服务器程序如Apache和wu-FTP,都用daemon进程的形式实现。很多Linux下常见的命令如inetd和ftpd,末尾的字母d通常就是指daemon。
前提知识:
进程组
概念和特性
进程组,也称之为作业。BSD于1980年前后向Unix中增加的一个新特性。代表一个或多个进程的集合。每个进程都属于一个进程组。在waitpid函数和kill函数的参数中都曾使用到。操作系统设计的进程组的概念,是为了简化对多个进程的管理。
当父进程,创建子进程的时候,默认子进程与父进程属于同一进程组。进程组ID第一个进程ID(组长进程)。所以,组长进程标识:其进程组ID其进程ID
可以使用kill -SIGKILL -进程组ID(负的)来将整个进程组内的进程全部杀死。 【kill_multprocess.c】
组长进程可以创建一个进程组,创建该进程组中的进程,然后终止。只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关。
进程组生存期:进程组创建到最后一个进程离开(终止或转移到另一个进程组)。
一个进程可以为自己或子进程设置进程组ID
进程组操作函数
getpgrp函数
获取当前进程的进程组ID
pid_t getpgrp(void); 总是返回调用者的进程组ID
getpgid函数
获取指定进程的进程组ID
pid_t getpgid(pid_t pid); 成功:0;失败:-1,设置errno
如果pid = 0,那么该函数作用和getpgrp一样。
setpgid函数
改变进程默认所属的进程组。通常可用来加入一个现有的进程组或创建一个新进程组。
int setpgid(pid_t pid, pid_t pgid); 成功:0;失败:-1,设置errno
将参1对应的进程,加入参2对应的进程组中。
注意:
- 如改变子进程为新的组,应fork后,exec前。
- 权级问题。非root进程只能改变自己创建的子进程,或有权限操作的进程
会话
创建会话
创建一个会话需要注意以下6点注意事项:
- 调用进程不能是进程组组长,该进程变成新会话首进程(session header)
- 该进程成为一个新进程组的组长进程。
- 需有root权限(ubuntu不需要)
- 新会话丢弃原有的控制终端,该会话没有控制终端
- 该调用进程是组长进程,则出错返回
- 建立新会话时,先调用fork, 父进程终止,子进程调用setsid
getsid函数
获取进程所属的会话ID
pid_t getsid(pid_t pid); 成功:返回调用进程的会话ID;失败:-1,设置errno
pid为0表示察看当前进程session ID
ps ajx命令查看系统中的进程。参数a表示不仅列当前用户的进程,也列出所有其他用户的进程,参数x表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j表示列出与作业控制相关的信息。
组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程。
setsid函数
创建一个会话,并以自己的ID设置进程组ID,同时也是新会话的ID。
pid_t setsid(void); 成功:返回调用进程的会话ID;失败:-1,设置errno
调用了setsid函数的进程,既是新的会长,也是新的组长。
守护进程的特性:
守护进程最重要的特性是后台运行。
其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符、控制终端、会话和进程组、工作目录已经文件创建掩码等。这些环境通常是守护进程从父进程那里继承下来的。
守护进程的启动方式
daemon进程的编程规则(5步)
(1)创建子进程,父进程退出
pid = fork();
if(pid > 0){
exit(0);
}
在子进程中创建新会话:
(2)使用系统函数setsid()。
由于创建守护进程的第一步调用了fork函数来创建子进程,再将父进程退出。由于
在调用fork函数的时候,子进程全盘拷贝了父进程的会话期、进程组、控制终端等,虽
然父进程退出了,但会话期、进程组、控制终端并没有改变,因此,还不是真正意义
上的独立开来。而调用setsid函数会创建一个新的会话并自任该会话的组长,调用setsid
函数有下面3个作用:让进程摆脱原会话的控制,让进程摆脱原进程组的控制,让进程
摆脱原控制终端的控制;
(3)改变当前目录为根目录:
使用fork函数创建的子进程继承了父进程的当前工作目录。由于在进程运行中,当
前目录所在的文件是不能卸载的,这对以后的使用会造成很多的不便。
利用chdir("/"); 把当前工作目录切换到根目录。
(防止占用可卸载的文件系统,也可以换成其它路径)
(4)重设文件权限掩码:
umask(0);
将文件权限掩码设为0,Deamon创建文件不会有太大麻烦;
防止继承的文件创建屏蔽字拒绝某些权限,增加守护进程灵活性
(5)关闭所有不需要的文件描述符:
新进程会从父进程那里继承一些已经打开了的文件。这些被打开的文件可能永远
不会被守护进程读写,而它们一直消耗系统资源。另外守护进程已经与所属的终端失
去联系,那么从终端输入的字符不可能到达守护进程,守护进程中常规方法(如
printf)输出的字符也不可能在终端上显示。所以通常关闭从0到MAXFILE的所有文件
描述符。
for(i=0;i<MAXFILE;i++)
close(i);
(注:有时还要处理SIGCHLD信号signal(SIGCHLD, SIG_IGN);防止僵尸进程(zombie))
Linux系统编程——Daemon进程的更多相关文章
- linux系统编程之进程(一)
今天起,开始学习linux系统编程中的另一个新的知识点----进程,在学习进程之前,有很多关于进程的概念需要了解,但是,概念是很枯燥的,也是让人很容易迷糊的,所以,先抛开这些抽象的概念,以实际编码来熟 ...
- linux系统编程之进程(八):守护进程详解及创建,daemon()使用
一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而且提供某种服务,不是对整个 ...
- linux系统编程之进程(五)
今天继续学习系统编程,学习的主题还是进程,今天主要讨论的是守护进程相关的概念,开始进入正题: 什么是守护进程: 守护进程的创建步骤: 在描述它之前,首先得先了解两个概念:进程组.会话期: ...
- linux系统编程之进程(六):父进程查询子进程的退出,wait,waitpid
本节目标: 僵进程 SIGCHLD wait waitpid 一,僵尸进程 当一个子进程先于父进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行,或者父进程调用了wait才告终止. ...
- linux系统编程--守护进程,会话,进程组,终端
终端: 在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal), 进程中,控制终端是保存在PCB中的信息,而f ...
- linux系统编程之进程(二):进程生命周期与PCB(进程控制块)
本节目标: 进程状态变迁 进程控制块 进程创建 进程撤消 终止进程的五种方法 一,进程状态变迁 进程的三种基本状态 就绪(Ready)状态 当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便 ...
- linux系统编程之进程(三):进程复制fork,孤儿进程,僵尸进程
本节目标: 复制进程映像 fork系统调用 孤儿进程.僵尸进程 写时复制 一,进程复制(或产生) 使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文.进程堆栈. ...
- Linux系统编程之进程概念
注:本文部分图片来源于网络,如有侵权,请告知删除 1. 什么是进程? 在了解进程概念之前,我们需要先知道程序的概念. 程序,是指编译好的二进制文件,这些文件在磁盘上,并不占用系统资源. 进程,指的是一 ...
- linux系统编程之进程(七):system()函数使用
一,system()理解 功能:system()函数调用"/bin/sh -c command"执行特定的命令,阻塞当前进程直到command命令执行完毕 原型: int syst ...
随机推荐
- Python 多进程和多线程的效率对比
import time from threading import Thread from multiprocessing import Process def f1(): # time.sleep( ...
- Socket通信方面
服务端 Console.WriteLine("Starting "); Socket listener = new Socket(AddressFamily.InterNetwor ...
- 【EMV L2】Select PSE应用选择相关的卡片数据格式
The data field of the response message contains the FCI specific to the selected PSE, DDF, or ADF. 一 ...
- Mysql数据库账户权限设置
1.修改mysql数据库的root密码: 修改 数据库.表名 SET password=加密(‘密码’) where user=’root’; UPDATE mysql.user SET passwo ...
- python-markdown
python-markdown无法将“`生成标签问题解决方法 2种都是代码区块 ```swift is Int ``` is Int
- Html中video的属性和方法大全
<video>标签的属性 src :视频的属性 poster:视频封面,没有播放时显示的图片 preload:预加载 autoplay:自动播放 loop:循环播放 controls:浏览 ...
- 从CSS到houdini
0. 前言 平时写CSS,感觉有很多多余的代码或者不好实现的方法,于是有了预处理器的解决方案,主旨是write less &do more.其实原生css中,用上css变量也不差,加上bem命 ...
- 走过的easyui的坑--datagrid的reload在IE下未刷新
至于为什么要进easyui这个坑,就不多说了. 我现在使用的是1.5这个版本,在用它做一个后台管理系统,项目做到一半,才想起记录这些坑. 1.对于datagrid在reload.load在IE下未刷新 ...
- getRealPath()和getContextPath()的区别
转载自:http://sucre.iteye.com/blog/319178 在程序中常常要获取文件的路径,有的时候需要用到相对路径而有的时候就要用到绝对路径,一提到绝对路径大家一定想到了getRea ...
- 关于PHP 缓冲区: ob_star , ob_get_contents
PHP ob_star ob_get_contents 细说 作者:田园花香 关于PHP 缓冲区 ob_start: 打开输出缓冲区,当缓冲区激活时,所有来自PHP程序的非头文件信息均不会发送, ...