守护进程

2023-05-16

5、 守护进程

​ 守护进程(daemon) 是生存期长的一种进程。它们常常在系统引导装入时启动,仅在系统关闭时才终止。因为它们没有控制终端,所以说它们是在后台运行的。UNIX系统有很多守护进程,它们执行日常事务活动。

5.1 编程规则

(1) 调用umask

首先要做的是调用umask将文件模式创建屏蔽字设置为一个已知值(通常是0)因为继承来的umask 是linux系统的一般是0022,当设置为有 r 权限时,便会被屏蔽掉,那么这并不是我们想得到的结果

(2) 调用fork,然后父进程exit

​ 这样做实现了下面几点:第一,如果该守护进程是作为一条简单的shell命令启动的,那么父进程终止会让shell认为这条命令已经执行完毕。第二,虽然子进程继承了父进程的进程组ID,但获得了一个新的进程ID,这就保证了子进程不是一个进程组的组长进程。 这是下面要进行setsid调用的先决条件。

(3) 调用setsid创建一个新会话

如果调用此函数的进程_不是一个进程组的组长_, 则函数创建一个新会话。具体会发生一下3件事

​ (1) 该进程变成新会话的会话首进程(session leader, 会话首进程是创建该会话的进程)。此时,该进程是新会话中的唯一进程。

​ (2) 该进程称为一个新进程组的组长进程。 新进程组ID是该调用进程的进程ID

​ (3) 该进程没有控制终端。如果在调用setsid之前该进程有一个控制终端,那么这种联系也被切断

如果该调用进程已经是一个进程组的组长,则次函数返回出错。 为了保证不处于这种情况,通常先调用fork然后服进行exit,而子进程继续。 因为子进程继承了父进程的进程组ID,而其进程ID是新分配的,两者不可能相等,这就保证了子进程不是一个进程组的组长

会话 是一个或多个进程组的集合。

因为父进程是进程组的组长,那么其已经有了一个会话,而子进程也在这个会话中;

而我们需要摆脱原来的独立出来

让进程摆脱原会话,原进程组,原终端的控制

(4) 将当前工作目录更改为根目录

执行chdir("/") 将当前工作目录更改为根目录

​ 从父进程继承过来的当前工作目录可能在一个挂载的文件系统中。例如守护进程的工作目录是在u盘中,但是当u盘一被弹出程序也就不能正常运行了。

(5)关闭不再需要的文件描述符

关闭stdin/stdout/stderr, 因为这些默认都是输出到终端的。而守护进程并不需要控制终端。

关于为什么需要使用setsid

​ setsid,创建新的session,因为session leader调用setsid不会创建新session,所以我们才需要之前的那个fork。
那session到底是什么?当你通过控制台登录时,你就创建了一个session,一个session就是一个controlling terminal、一个controlling process group,再加上一堆后台process group,其中controlling process一般就是login shell,controlling terminal就是你在敲键盘看显示器的那个“终端”。 在shell中,你可以用"&"将一个命令在后台运行,或者你可以按Ctrl-Z,然后用bg命令将其放入后台,这时你可以用jobs命令看到后台运行的进程,这些后台进程就是background process group
看看当你logout的时候会发生什么,此时controlling terminal会被关闭,这个session中所有进程都会收到SIGHUP和SIGTERM/SIGQUIT,对于这些信号的缺省操作就是结束进程。

例如使用"&" 运行一个后台进程,当退出终端时,此时这个会话终止,这个会话中的所有进程接收到SIGHUP和SIGTERM/SIGQUIT信号,然后进程被结束

作为一个daemon,你当然不希望用户logout的时候就退出,解决方案有几种,一种就是忽略上述所有信号,例如nohup程序干的就是这个,但这样做有个小问题,很多程序使用信号作为一种简单的IPC机制,忽略这些信号会导致这种IPC失效;另外一种方案就是让进程从这个controlling terminal上脱离,setsid将会创建一个新的session,使当前进程成为新session的leader,并且不再关联之前session的controlling terminal。

3、第二次fork,这件事情有点晦涩,其实很多文档上并没说的太清楚,具体原因是这样的,即使一个进程创建了新的session,它依然有可能获得一个controlling terminal,比如你可以用ioctl(TIOCSCTTY),这样做的后果就是,新的session有了controlling terminal,然后前面我们提到的所有问题依然可能发生。为了彻底解决这个问题,我们需要第二次fork,因为ioctl(TIOCSCTTY)手册中在非常不起眼的地方提到了,只有session leader才能为session打开controlling terminal,第二次fork之后,子进程就是session中第二个进程,它这辈子再没机会成为session leader了(除非它调用setsid),也就再没能力打开controlling terminal了。这样我们就一劳永逸的解决了所有问题。

为了避免取得控制终端的另一种方法是,无论何时打开一个终端设备都一定要指定O_NOCTTY,如果成为了终端设备那么当终端退出的时候,程序也会退出

所以,如果你的程序行为很固定,你知道它不会无聊到去打开controlling terminal的话,第二次fork其实是不必要的,但是如果你是在写一个库,而且不知道使用它的程序到底会有什么样的行为,你最好还是再fork一次。

守护进程用例

#include<stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdlib.h>
void daemonize(const char *cmd)
{
	pid_t pid;
	int fd;
	struct rlimit rl;  //获取最大的文件描述符值	
	/** 1、清空umask */
	umask(0);	
	/*2、创建子进程 */
	if ((pid = fork()) < 0)
	{
		fprintf(stderr,"%s can't fork", cmd);
		exit(-1);
	}
	if (pid != 0) // 父进程
		exit(0);  
	/*3、setsid 创建新会话 子进程成为会话首进程*/
	setsid();
	/*4、将当前工作目录更改为 "/"*/
	chdir("/");
	if ((pid = fork()) < 0)  //使守护进程完全丧失打开终端的能力
	{
		fprintf(stderr, "%s can't fork\n", cmd);
		exit(-1);		
	}
	if (pid != 0) //父进程 
		exit(0);
	/*5、关闭所有的文件描述符*/
	if (getrlimit(RLIMIT_NOFILE, &rl) < 0)  //获取最高的描述符值
	{
		fprintf(stderr, "%s can't get file limit\n", cmd);
		exit(-1);
	}
	for (int i = 0; i < rl.rlim_max; i++)
		close(i);
	//捕捉SIGHUP信号  //因为守护进程已经和终端分离了,所以并不会接收到SIGHUP信号,捕捉此信号的原因是,当守护进程拥有配置文件时,如果修改了配置文件,则需要重新启动才可以,为了不停止再次启动,则可以向守护进程发送SIGHUP信号,然后让守护进程读取新的配置文件 并不是必须的
	fd = open("dev/null", O_RDWR); //返回0
	dup(fd); // 1
	dup(fd); // 2
	// /dev/null属于字符特殊文件,它属于空设备,是一个特殊的设备文件,它会丢弃一切写入其中的数据,写入它的内容都会永远丢失,而且没有任何可以读取的内容。	
}
int main(int argc,char *argv[])
{
	pid_t pid;
	daemonize("hello");	
	while(1){
		sleep(100);
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

守护进程 的相关文章

  • DS001-测试冒泡排序的运行时间

    本程序演示如何测试一段程序的运行时间 以冒泡排序算法为例 include 34 time h 34 与时间相关的函数 include 34 stdlib h 34 rand 函数在此库中 include 34 stdio h 34 输入输出
  • 嵌入式开发,裸机开发,中断,按键控制蜂鸣器。

    0 前言 最近想体验一下面试 xff0c 真正收到公司通知又有点无从下手 xff0c 没有做准备 但是反手一想 xff0c 既然是想体验 xff0c 锻炼而已 xff0c 干就完了 推荐一首歌 Timber MattyBRaps xff0c
  • 到底什么是MCU、MPU、CPU,和芯片是什么关系?区别又是什么?

    目录 0 前言 1 芯片 2 CPU 3 MPU 4 MCU 5 总结 0 前言 更新的是有点慢 xff0c 从这周开始吧 xff0c 应该会快一点 推荐一首歌 你到底有没有爱过我 蓝波 xff0c 额 xff0c 怎么说呢 xff0c 大
  • 从SLAM到视觉识别、VIO,大牛分享!

    用户分享汇总目录 01 双目惯性模组的初探与实践02 通过驱动字写数据采集程序03 INDEMIND双目惯性相机运行MSCFK04 利用开源识别算法进行车牌检测05 双目惯性模组导航项目分享项目简介 xff1a 车体结构 xff1a 技术简
  • zxing的使用及优化

    二维码介绍 zxing项目是谷歌推出的用来识别多种格式条形码的开源项目 xff0c 项目地址为 https github com zxing zxing xff0c zxing有多个人在维护 xff0c 覆盖主流编程语言 xff0c 也是目
  • INDEMIND带你玩转OpenCV4.0(一):DIS光流算法解析

    文章目录 一 xff0e OpencCV 4 0 新特性介绍首先是OpenCV完全支持了C 43 43 11DNN xff08 深度神经网络 xff09 模块是目前OpenCV更新最重要的模块G API 为算法的硬件优化加速提供计算图支持O
  • STM32 SWD烧录一次后J-LINK设备消失的问题

    偶然遇到移植程序时烧录一次后无法烧录的问题 如果用的时CUBEMX 应该马上检查SWDIO SWCLK的配置问题 如果无误 那就检查时钟问题 时钟问题有可能导致该问题的发生 看到有其它用户说在标准库的配置中添加 RCC AHB1Periph
  • IIC通讯详解笔记

    IIC概述 IIC总线是一种串行半双工两线总线 一根是双向的数据线SDA xff0c 另一根是时钟线SCL 所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上 xff0c 各设备的时钟线SCL接到总线的SCL上 硬件拓扑如下图所示
  • 关于Gitee的介绍和使用

    Gitee Gitee是开源中国 xff08 OSChina xff09 推出的基于Git的代码托管服务 Gitee xff08 码云 xff09 是开源中国社区推出的代码托管协作开发平台 xff0c 支持Git和SVN xff0c 提供免
  • webpack postcss-loader自动添加前缀版本问题

    报错 xff1a 问题所在 xff1a postcss loader版本问题 xff0c 用了5版本会报错 解决 xff1a 将postcss loader降低到4版本就解决此问题
  • 使用数据表反向生成以及出现问题汇总

    什么是正向以及反向生成 正向生成 xff0c 指的是先创建model py文件 xff0c 然后通过django内置的编译器 xff0c 在数据库如mysql中创建出符合model py的表 反向生成 xff0c 指的是先在数据库中crea
  • 解决svn文件图标不显示

    1 首先检查svn设置中是否设置图标显示 2 win 43 R xff0c 输入regedit xff0c 调出注册表信息 xff0c 按下Ctrl 43 F 在注册表里搜索 ShellIconOverlayIdentifiers 查看是否
  • vue父组件传值给子组件不生效

    先上代码 父组件 lt hj subjects v if 61 34 showHjSubect 34 list 61 34 subjectsList 34 64 getHjSubjects 61 34 getHjSubject 34 gt
  • vue下载pdf为空问题解决

    后端返回文件流 xff0c vue下载到本地 请求时需要设置responseType blob 否则下载pdf文件打开会为空 下载方法代码如下 xff1a url请求参数 params请求参数 filename文件名称 span class
  • vue使用iframe嵌入html

    1 本地html文件的存放 在根目录下找到public文件夹 xff0c 在public文件夹下创建static文件夹 xff0c 把html文件放入static文件夹中 2 使用iframe标签引入html文件 span class to
  • 解决Android运行过程中出现的NoClassDefFoundError

    1 先说一下出现上述问题的经过 出现这个问题是集成一个aar之后 xff0c 编译过程中没有问题 在安装运行的时候出现上述错误 然后百度各种解决办法都无济于事 但是有了一点思路 报错位置 在自定义的application中初始化的aar导致
  • 前端将base64图片格式转化为文件流并传给后端

    base64图片格式 xff1a base64图片格式转化为文件流代码 xff1a data base64图片格式字符串 filename xff1a 文件名称 base64toFile span class token punctuati
  • IP地址分类

    一 xff1a IP地址 1概念 xff1a a IP地址是指互联协议地址 xff0c 又译为网际协议地址 b IP地址是提供的IP协议一种统一地址格式 xff0c 它为互联网上的每一个网络和每一台主机分配一个逻辑地址 xff0c 以此来屏
  • vue项目打包npm run build报错

    报错如下图 xff1a 删除根目录下的package lock json和node modules文件 xff0c 再运行npm i命令 npm i命令运行完成后 xff0c 再输入npm run build命令 命令执行成功后 xff0c
  • SpringBoot运行报o.s.b.d.LoggingFailureAnalysisReporter

    报错截图 xff1a 报错原因 xff1a 从上图Description中可以看出 xff0c 报错原因是端口被占用 报错解决方法 xff1a 找到application yml文件 xff0c 修改端口为8081 xff08 或者关闭80

随机推荐

  • ROS教程 Gazebo仿真(3)-摄像头

    接上一篇 ROS教程 Gazebo仿真 2 激光雷达 https blog csdn net weixin 43928944 article details 115904044 配置摄像头 camera sensors xacro span
  • Ubuntu18 远程桌面 VNC-Server 配置[亲测]

    安装vino sudo apt update sudo apt install vino 设Enable VNC 服务 sudo ln span class token operator span s span class token pu
  • redis redisson 集合使用示例(RList、Rset、RMap)

    redis redisson 集合操作 相关类及接口 Rlist xff1a 链表 public interface RList lt V gt extends List lt V gt RExpirable RListAsync lt V
  • Python数据分析、挖掘常用工具

    Python语言 xff1a 简要概括一下Python语言在数据分析 挖掘场景中常用特性 xff1a 列表 xff08 可以被修改 xff09 xff0c 元组 xff08 不可以被修改 xff09 字典 xff08 lt k v gt 结
  • 17个新手常见Python运行时错误

    对于刚入门的Pythoner在学习过程中运行代码是或多或少会遇到一些错误 xff0c 刚开始可能看起来比较费劲 随着代码量的积累 xff0c 熟能生巧当遇到一些运行时错误时能够很快的定位问题原题 下面整理了常见的17个错误 xff0c 希望
  • Python 正在吞噬世界...

    Python is eating the world 这篇关于Python长文火了 从Python的创建过程 xff0c 到Python成为一个无所不在的语言 xff0c 究竟经历了一个怎样的过程 xff1f 美国科技媒体ZDNet记者Ni
  • 解决android studio错误提示信息乱码问题

    android studio在编译过程中 xff0c 如果出现错误会在messages界面给出提示 xff0c 但是有的时候会出现乱码的问题 导致根本看不出来是什么问题 这时候只要做以下设置就能解决乱码问题 xff0c IDE也会将出现的错
  • Python为什么是编程语言中最skr的?

    Python的出现让计算机编程语言不再是生僻的专业技能 xff0c 而是常人都能学习和使用的万金油 经济学人 xff08 Economist xff09 近日对Python的一篇专题报道 xff0c 揭秘了这一把计算机思维带入寻常百姓家的神
  • PLC有几种编程语言?各有什么特点?

    之前我们简单学习了PLC的一些基本知识 今天我们再来了解PLC的编程语言吧 IEC 1131 3的编程语言是IEC工作组对世界范围的PLC厂家的编程语言合理地吸收 借鉴的基础上形成的一套针对工业控制系统的国际编程语言标准 xff0c 它不但
  • 几种主流编程语言

    著名风险投资家Marc Andreessen曾说 xff1a 软件正在吞噬整个世界 没错 xff0c 开发软件的公司越来越多了 xff0c 会编程的人也越来越多了 xff0c 现在的世界上光编程语言就达成千上万种 xff0c 尽管这其中只有
  • VB编程语言基础知识点总结(转)

    Visual Basic xff08 简称VB xff09 是Microsoft公司开发的一种通用的基于对象的程序设计语言 xff0c 为结构化的 模块化的 面向对象的 包含协助开发环境的事件驱动为机制的可视化程序设计语言 海风教育投诉 海
  • 如何学习SCL语言?SCL语言编程入门

    随着现代工控技术的不断发展 xff0c 可能很多使用过 PLC 的技术人员都有这么一个感受 xff1a 传统的 梯形图 编程方式在面对越来越复杂的控制要求时 xff0c 已显得力不从心 海风教育投诉 海风教育在线辅导0元一对一试听课等你来领
  • 量子计算机有多可怕 一秒破译全世界所有密码!

    导语 xff1a 最近半年以来 xff0c 人工智能的发展重心逐渐从云端向终端转移 xff0c 相伴而生的是全新一代的计算芯片产业全面崛起 智东西历经数月 xff0c 首次对包括AI芯片在内的新一代计算芯片全产业链上下近百间核心企业进行报道
  • 十大编程语言都有哪些?学哪种比较好?

    很多同学想转行编程 xff0c 但是那么多的编程语言到底该怎么选呢 xff1f 头疼 如果你是一名具有前瞻性的开发者或者想成为一名具有前瞻能力的开发者的话 xff0c 那么 xff0c 你应该至少在最好的编程语言中选择一个 xff0c 类似
  • 偏导数,雅可比矩阵(jacobi matrix),黑塞矩阵(Hessian matrix)

    这里我们大致地复习一下偏导数 xff0c 雅克比矩阵以及黑塞矩阵的定义和关系 导数向量与雅克比矩阵 xff08 Jacobi matrix xff09 函数的某个因变量对某个自变量求的导数即为它们关于函数的偏导数 当因变量为一元的情况下 x
  • 数据挖掘-Matplotlib画图示例1---操作多画布plt.subplots

    数据挖掘Matplotlib 画图示例 plt plot 折线图 import random import matplotlib pyplot as plt 这个是解决中文编码问题的 方法一 plt rcParams 39 font san
  • HIVE操作语句--DDL篇

    未经允许 xff0c 禁止转载 xff0c 一经发现 xff0c 必定严究 HIVE 1 1 创建数据库1 2 查看所有数据库1 3 查看数据库信息1 xff09 显示数据库信息2 xff09 显示数据库详细信息 1 4 删除数据库1 xf
  • 关于studio编译过程中出现的Execution failed for task ':maodiandian:processDebugManifest'

    android studio在编译过程中 xff0c 由于添加第三方的依赖 可能导致manifest文件和并失败 xff0c 报以以下错误 xff1a org gradle api tasks TaskExecutionException
  • 阿里云 腾讯云 服务器Ubuntu 20.04安装图形界面,解决灰屏问题,解决复制粘贴问题,并调整分辨率大小

    参考 xff1a https blog csdn net weixin 39278265 article details 118641412 https help aliyun com document detail 59330 html
  • 守护进程

    5 守护进程 守护进程 daemon 是生存期长的一种进程 它们常常在系统引导装入时启动 xff0c 仅在系统关闭时才终止 因为它们没有控制终端 xff0c 所以说它们是在后台运行的 UNIX系统有很多守护进程 xff0c 它们执行日常事务