网络入门---守护进程

目录标题

  • 什么是守护进程
  • 会话的理解
  • setsid函数
  • daemonSelf函数模拟实现
  • 测试

什么是守护进程

在前面的学习过程中我们知道了如何使用TCP协议和UDP协议来实现通信,比如说登录xshell运行了服务端:
在这里插入图片描述
然后再登录一个xshell运行客户端并向服务端发送信息:
在这里插入图片描述
服务端就会将接收到的消息打印出来:
在这里插入图片描述
但是这里就存在这么一个疑问?我们把运行服务端的xshell关掉这里的通信还能正常的实现吗?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到把运行服务端的xshell关闭之后客户端也会跟着出现问题,那么这是不符合我们的预期的,我们希望看到的是:服务端的运行不受xshell的登录或者注销的影响,除非我们手动的使用kill指令将其关闭,那么我们把不受用户登录或者注销的进程称之为守护进程,那么本篇文章就要将我们之前写的程序变成守护进程。

会话的理解

首先我们的linux服务器就就是下面图片的一个大方框,xshell就是下面图片中的一个小方框:
在这里插入图片描述
每当我们登录xshell的时候,xshell就会在linux主机上创建一个会话,在会话里面就有一个进程用来做命令行解释器也就是bash:
在这里插入图片描述
然后在这个会话里面我们还可以创建其他的进程(也可以叫做任务或者作业)
在这里插入图片描述
在一个会话里面只能同时存在一个前台任务和一个或者多个后台任务,比如说当前的前台任务就是命令行解释器bash,我们可以通过bash执行各种指令:
在这里插入图片描述
但是将TCP的服务端运行之后我们可以看到这些指令是无法执行了:
在这里插入图片描述
那么这就是因为一个会话只能有一个前台进程,运行了服务端可执行程序之后服务端就变成了前台,bash就来到了后台,所以这个时候我们输入的指令是无法被bash读取的,我们先让程序终止然后在运行程序的指令后面添加&符号就可以让一个程序在后端运行不影响bash的指令读取:
在这里插入图片描述

使用jobs指令可以查看当前会话有几个后台进程正在运行,因为我们就运行了一个所以下面的图片就只显示了一个:
在这里插入图片描述
我们可以再使用sleep指令在后台多运行几个进程,然后就可以看到jobs显示的后台任务会变多:
在这里插入图片描述
最前面的数字表示这是几号作业,tcpserver就是2号作业,sleep 3 4 5就是3号作业,sleep 6 7 8就是4号作业,数字后面的Running就表示当前的作业是运行状态,使用grep指令查看进程就可以看到下面这样的内容:
在这里插入图片描述
仔细的观察不难发现进程sleep3 4 5的pid分别为3574 3575 3576是一段连续数字,进程sleep 6 7 8的pid分别为3651 3652 3653又是另外一段连续的数字,进程的pid如果是连续的话就说明这些进程之间的关系是兄弟关系,这些兄弟进程就属于同一个进程组,也就是说sleep345是一个进程组,sleep678又是另外一个进程组,一个进程组中可能会存在多个兄弟进程,但是一个进程组中必须得有一个老大,这个老大就是进程组中第一个被创建的进程,大家网上翻一下就不难发现sleep 30000是进程组中第一个被创建的,sleep 60000也是进程组中第一个被创建,每个进程都有一个PGID来记录当前组的组长是谁,如果自己的PID和PGID相等的话就说明你就是组长,该组其他的兄弟进程的PGID就记录着你的PID:
在这里插入图片描述
一个进程组的所用成员共同来完成一个作业,这就好比工地中的甲方会讲工地上的各种任务分给多个包工头,那么包工头就是组长,包工头又会号召很多其他的工人来共同完成不同的任务。图片中还有一个SID:
在这里插入图片描述
虽然当前的sleep进程分为两个不同的进程组,但是这些进程组成员的SID都是一样的都为2373,那么这个SID就是xshell给我们创建的会话id,SID的全称就是session id。使用指令fg加作业号可以将后台的作业调整到前台来运行:
在这里插入图片描述
使用ctrl +z就可以将前台作业全部暂停,暂停之后就会默认将bash调到前台继续运行,并且通过jobs指令也可以看到3号作业的状态由之前的running变成stoped
在这里插入图片描述
使用指令bg加作业号就可以将后台暂停的作业变成运行状态:
在这里插入图片描述
所以通过上面的实验我们证明了一个会话中可以存在多个进程,这些进程中只能有一个是前台进程但是可以有多个后台进程,并且不同的进程可以通过指令来做到前后台转换,创建一个会话的时候会创建多个进程或者作业,那么当我们关闭xshell时这个会话就会被销毁,那销毁之后这个会话创建出来的是前台进程还是后台进程都将不复存在这也是为什么上面xshell关闭之后服务端不能正常运行的原因,那么要想服务端不受xshell关闭的影响我们就得自成会话,自成进程组和终端设备无关就好比要想不受老板的骂要想不被强制加班就得主动辞职自己创建一个公司当老板:
在这里插入图片描述

setsid函数

实现守护进程有很多的方式,其中操作系统以及给我们提供了专门用来实现守护进程的接口deamon
在这里插入图片描述
但是该接口在实现的过程中会遇到很多未定义的问题,所以我们接下来在实现守护进程的时候就不使用该接口而是自己模拟实现一个daemon函数。要想实现守护进程就必须得调用setsid函数:
在这里插入图片描述
该函数的作用就是哪个进程调用setsid函数哪个进程就能够自成一个会话,会话的id就是该进程的pid,该进程也就变成了组长,进程调用该函数有一个前提就是该进程不能是组长,只有非组长进程才能调用setsid函数,这就好比只有普通员工跳槽辞职创建公司当老板,哪有公司老板辞职又去创建公司的呢!

daemonSelf函数模拟实现

该函数我们主要完成下面三件事情,第一:让调用进程忽略掉异常的信号,因为有些客户端可能会搞事情,比如说客户端给服务端发送了一条消息,服务端刚准备发送一条消息给客户端时,客户端就关闭这就好比向一个已经关闭的文件中写入内容,这时就会收到异常的信号从而影响到服务端的运行,所以第一步就是忽略掉一些异常信号,第二:因为组长进程无法调用setsid函数所以第二件事就是如何让当前的调用进程不再是组长。第三:因为守护进程是脱离终端的那所以就不需要向终端的上面显示数据和读取数据,所以就需要关闭或者重定向之前进程默认打开的一些文件。

void daemonSelf()
{//忽略掉一些异常信号//让自己不再是组长//关闭之前默认打开的文件
}

第一件事情很简单直接使用signal函数将SIGPIPE信号忽略即可:

void daemonSelf()
{//忽略掉一些异常信号signal(SIGPIPE, SIG_IGN);//让自己不再是组长//关闭之前默认打开的文件
}

对于第二件事我们可以创建使用fork函数创建一个子进程,因为父进程先被创建所以他就是组长,子进程不是,那么我们就可以通过if语句和exit让父进程直接退出,子进程执行setsid函数,setsid可能会执行失败,所以创建一个变量记录函数的返回值并判断会不会出现错误:

void daemonSelf()
{//忽略掉一些异常信号signal(SIGPIPE, SIG_IGN);//让自己不再是组长 if (fork() > 0)exit(0);// 子进程 -- 守护进程,精灵进程,本质就是孤儿进程的一种!pid_t n = setsid();assert(n != -1);//关闭之前默认打开的文件
}

第三件事我们不能直接关闭默认打开的0 1 2文件,因为我们不能完全保证调用的程序中不会向这些文件发送或者读取问题,一旦出现了就可能会出现问题,所以我们这里就采用这样的方法,系统中存在这么一个文件:/dev/null,他是一个黑洞文件任何进程都可以向他发送任何的数据,但是任何进程也不能从这个文件中读取到任何的数据
在这里插入图片描述
所以为了防止出现上面所述的问题,我们可以将0 1 2重定向到黑洞文件里面,所以我们这里先使用open函数打开黑洞文件,如果打开成功就使用dup2重定向,如果打开失败就只能关闭0 1 2,那么这里的代码如下:

#define DEV "/dev/null"void daemonSelf(const char *currPath = nullptr)
{// 1. 让调用进程忽略掉异常的信号signal(SIGPIPE, SIG_IGN);// 2. 如何让自己不是组长,setsidif (fork() > 0)exit(0);// 子进程 -- 守护进程,精灵进程,本质就是孤儿进程的一种!pid_t n = setsid();assert(n != -1);// 3. 守护进程是脱离终端的,关闭或者重定向以前进程默认打开的文件int fd = open(DEV, O_RDWR);if(fd >= 0){dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}else{close(0);close(1);close(2);}
}

完成了上面三步我们就基本上实现了该函数的主要内容,但是在函数最后我们还可以做一些其他的事情比如说切换当前进程的执行路径等等,那么完整的代码就如下:

#pragma once#include <unistd.h>
#include <signal.h>
#include <cstdlib>
#include <cassert>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define DEV "/dev/null"void daemonSelf(const char *currPath = nullptr)
{// 1. 让调用进程忽略掉异常的信号signal(SIGPIPE, SIG_IGN);// 2. 如何让自己不是组长,setsidif (fork() > 0)exit(0);// 子进程 -- 守护进程,精灵进程,本质就是孤儿进程的一种!pid_t n = setsid();assert(n != -1);// 3. 守护进程是脱离终端的,关闭或者重定向以前进程默认打开的文件int fd = open(DEV, O_RDWR);if(fd >= 0){dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}else{close(0);close(1);close(2);}// 4. 可选:进程执行路径发生更改if(currPath) chdir(currPath);
}

测试

#include"tcpserver.hpp"
#include<memory>
#include<stdlib.h>
#include"daemon.hpp"
#include"log.hpp"
static void Usage(string proc)
{cout << "\nUsage:\n\t" << proc << " serverport\n\n";
}
int main(int args,char* argv[])
{int sock=3;if(args!=2){Usage(argv[0]);exit(1);}uint16_t port=atoi(argv[1]);unique_ptr<tcpserver> tcil(new tcpserver(port));tcil->inittcpserver();daemonSelf();tcil->start();return 0;
}

在服务端运行之前我们先调用daemon函数使其变成守护进程,然后运行服务端:
在这里插入图片描述
可以看到运行之后bash依然存在,然后我们再运行客户端:
在这里插入图片描述
是可以直接运行的,并且我们关掉服务端再输入消息时也不会有任何的影响:
在这里插入图片描述
那么这就是守护进程的概念和模拟实现,希望大家能够理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/224798.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于若依搭建微服务nacos版本(ruoyi-Cloud前后端分离)

说明&#xff1a;本文介绍基于Ruoyi-Cloud前后端分离nacos版本的微服务从0到1的搭建过程&#xff0c;同时新增一个新的微服务模块。是基于官方文档的补充说明&#xff0c;需要结合Ruoyi-Cloud的官方文档 https://doc.ruoyi.vip/ruoyi-cloud/ 如果直接查看官方文档便可成功部署&…

Linux--权限问题(2)

目录 前文 前言 1. 文件的权限 1.1 文件的访问者分类 1.2 文件类型和访问权限&#xff08;事物属性&#xff09; 2. 如何修改文件的权限 3.对比权限有无的表现 4.修改用户角色 5.修改权限的第二种做法 6.目录的权限 7.默认权限 前文 Linux--权限问题&#xff08;1&#…

云原生之深入解析Kubernetes本地持久化存储方案OpenEBS LocalPV的最佳实践

一、K8s 本地存储 K8s 支持多达 20 种类型的持久化存储&#xff0c;如常见的 CephFS 、Glusterfs 等&#xff0c;不过这些大都是分布式存储&#xff0c;随着社区的发展&#xff0c;越来越多的用户期望将 K8s 集群中工作节点上挂载的数据盘利用起来&#xff0c;于是就有了 loca…

一种用于心音分类的轻量级1D-CNN+DWT网络

这是由National Institute of Technology Rourkela, Central University of Rajasthan发布在2022 ICETCI的论文&#xff0c;利用离散小波变换(DWT)得到的多分辨率域特征对1D-CNN模型进行心音分类训练。 预处理& DWT 由于FHS和各种病理声的频率范围在500hz以下[5]&#xff…

像素、分辨率、频率、精度、延迟,关于光学动作捕捉镜头参数的那些事

精准度、分辨率、频率、延迟等参数是影响光学动作捕捉效果和还原度的关键因素。下面逐一介绍NOKOV度量动作捕捉系统的基础参数。 NOKOV度量动作捕捉系统的核心产品是光学动作捕捉镜头&#xff0c;用于捕捉被测物表面反光标记点的三维坐标数据。 从表中可以看到&#xff0c;不同…

电阻的运用

本文引注 https://baijiahao.baidu.com/s?id1749115196647029942&wfrspider&forpc 一、零欧电阻 在电子电路设计时经常用到的一种元件就是电阻&#xff0c;我们都知道电阻在电路中起到分压限流的作用。然而&#xff0c;实际使用时会用到一种特殊的电阻&#xff1a;零…

用Kotlin抓取微博数据并进行热度预测

闲来无事&#xff0c;逛逛微博&#xff0c;看着每条热度很高的博文趣事&#xff0c;心想能否通过爬虫抓取微博热度并进行趋势分析&#xff0c;说干就干&#xff0c;这里需要注意的问题我会一一标注。 爬虫ip信息的设置是在爬虫程序中进行的。爬虫ip信息可以帮助爬虫程序在访问…

使用React实现随机颜色选择器,JS如何生成随机颜色

背景 在标签功能中&#xff0c;由于有「背景色」属性&#xff0c;每次新增标签时都为选择哪种颜色犯难。因此&#xff0c;我们思考如何通过JS代码生成随机颜色&#xff0c;提取一个通用的随机颜色生成工具&#xff0c;并基于React框架封装随机颜色选择器组件。 实际效果 原理…

Parade Series - Message Interaction

if (true) {Swal.fire("节目发布", "发布完毕", "success");event.preventDefault(); } if (false) {Swal.fire("节目发布", "发布失败", "error");event.preventDefault(); }if (true) {for (var i 0; i < b…

AI日报:OpenAI向新用户重新开放ChatGPT Plus订阅

欢迎订阅专栏 《AI日报》 获取人工智能邻域最新资讯 文章目录 总览Chatgptplus重新开放订阅#暂停原因功能 OpenAI的1000万美元安全人工智能拨款拨款初衷学术捐赠 总览 ChatGPT Plus再次向新用户开放&#xff0c;但目前每三小时限制发送40条消息。 OpenAI还宣布拨款1000万美元…

数据结构-07-二叉树

前面学习的栈、队列等等都是线性表结构。树是一种非线性表结构&#xff0c;比线性表的数据结构要复杂。 1-树tree “树”这种数据结构类似我们现实生活中的“树”&#xff0c;这里面每个元素我们叫作“节点”&#xff1b;用来连线相邻节点之间的关系&#xff0c;我们叫作“父子…

云端赋能大湾区:华为云照亮数字化转型之路

编辑&#xff1a;阿冒 设计&#xff1a;沐由 在中国的经济版图上&#xff0c;大湾区是极其重要的增长引擎。这块富有活力和创新力的经济区域里&#xff0c;荟聚了大量的高新技术企业&#xff0c;以及一批创新孵化器和科研机构&#xff0c;产业升级和技术创新的氛围格外浓烈。 1…

山峰个数 - 华为OD统一考试

OD统一考试 分值: 100分 题解: Java / Python / C++ 题目描述 给定一个数组,数组中的每个元素代表该位置的海拔高度。0表示平地,>=1时表示属于某个山峰,山峰的定义为当某个位置的左右海拔均小于自己的海拔时,该位置为山峰。数组起始位置计算时可只满足一边的条件。 …

lv12 linux内核的安装与加载

目录 1 tftp加载Linux内核及rootfs 1.1 uboot内核启动命令 1.2 uboot自启动参数环境变量 1.3 实验 2 EMMC加载Linux 内核及rootfs ​编辑 2.1 emmc中写入uimage ​编辑 2.2 emmc中写入dtb 2.3 emmc中写入根文件系统 2.4 设置环境变量 3 tftp加载Linux内核nfs挂载ro…

centos 手动编译安装git

原因 由于centos自带的git版本太低&#xff0c;使用git的时候会出现很多问题&#xff0c;但是尝试了各种办法无法直接更新git版本&#xff0c;所以最后自己手动编译安装git 在github下载源码&#xff0c;下载解压之后&#xff0c;上传到服务器&#xff0c;我上传到 /home/user…

探索多功能SQL数据库编辑器 - Richardson Software RazorSQL

在当今数字化时代&#xff0c;SQL数据库的管理和编辑是许多企业和开发人员必不可少的任务。为了提高生产力和简化数据库操作&#xff0c;Richardson Software推出了一款强大而多功能的SQL数据库编辑器 - RazorSQL。 RazorSQL是一款功能全面的数据库管理工具&#xff0c;可适用…

LeetCode(61)删除链表的倒数第 N 个结点【链表】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 删除链表的倒数第 N 个结点 1.题目 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例…

【STM32独立看门狗(IWDG) 】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、看门狗是什么&#xff1f;1.简介2. 主要功能3.独立看门狗如何工作4.寄存器写保护5.看门狗 看门时间 二、使用步骤1.开启时钟2.初始化看门狗3.开启看门狗4.喂…

ACL和NAT

文章目录 ACL和NAT一、ACL概述及产生背景1、ACL访问控制列表2、ACL工作原理3、ACL种类4、ACL命令配置步骤4.1 ACL命令配置4.1 ACL配置步骤 二、NAT&#xff08;网络地址转换&#xff09;1、NAT概述2、NAT类型2.1 静态NAT与动态NAT 3、NATPT&#xff08;端口映射&#xff09;4、…

详解—【C++】lambda表达式

目录 前言 一、lambda表达式 二、lambda表达式语法 2.1. lambda表达式各部分说明 2.2. 捕获列表说明 三、函数对象与lambda表达式 前言 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法。 #include <algorithm> #i…