当前位置: 首页 > news >正文

【Linux网络编程六】服务器守护进程化Daemon

【Linux网络编程六】服务器守护进程化Daemon

  • 一.背景知识:前台与后台
  • 二.相关操作
  • 三.Linux的进程间关系
  • 四.自成会话
  • 五.守护进程四步骤
  • 六.服务器守护进程化

一.背景知识:前台与后台

在这里插入图片描述

核心知识就是一个用户在启动Linux时,都会给一个session会话,这个会话里会存在一个前台进程,和多个后台进程。

在这里插入图片描述

二.相关操作

在这里插入图片描述

三.Linux的进程间关系

Linux中的进程之间的关系,不仅仅是相互独立的,还可以过程进程组,进程组的组长就是第一个进程的pid。
在这里插入图片描述

四.自成会话

在这里插入图片描述
当一个任务以后台进程在会话中执行,然后我们将会话关闭,重新启动一个会话,将会发现这个任务虽然还存在,但其实已经不再是原先的那个任务了,因为它的父进程bash已经退出,它被系统自动领养了。(它原来的会话是会被记录下来的)

所以进程组是会收到用户的登录和退出的影响。进程组就代表着一个任务,也就是任务是会收到用户的退出影响,用户一旦退出,那么该任务就不再属于你了,也就是该任务已经没有了。你把会话都关闭了,那么里面的所有任务都会不存在了。

这里我想说的就是我们想让一个任务一直执行,不受用户的登录和退出影响,就必须使用守护进程!
守护进程的核心就是自成会话。
在这里插入图片描述
在这里插入图片描述
因为创建新会话的进程不能是进程组里的组长,所以我们就直接让当前进程创建子进程,然后再让当前进程直接退出,让子进程创建会话。

五.守护进程四步骤

守护进程四步骤:①忽略其他信号②自成会话③更改工作目录④重定向标准输入与输出。
在这里插入图片描述
因为自成会话后,新会话就不再与终端有联系了,就不需要标准输出和标准输入和标准错误了。
而打印日志可以直接往文件里输入。

其实系统中提供了守护进程化的接口调用:
在这里插入图片描述

六.服务器守护进程化

其实守护进程的本质就是后台进程,服务器一旦启动了守护进程化,那么就不会受用户的退出影响,就会一直在运行。

//守护进程
#pragma once#include <signal.h>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>const std::string nullfile="/dev/null";
void Daemon(const std::string &cwd="")
{//第一步忽略其他异常信号,防止被信号杀死signal(SIGCLD,SIG_IGN);signal(SIGPIPE,SIG_IGN);signal(SIGSTOP,SIG_IGN);//第二步将自己变成新的会话,不受其他会话管理if(fork()>0)exit(0);//让孙子进程来创建新的会话,因为自成组长的进程不能创建新会话setsid();//让使用该函数的进程创建新的会话,并属于该会话//第三步更改当前进程的路径//根据需要传入不同的路径就更改到不同路径下if(!cwd.empty()){chdir(cwd.c_str());}//第四步,将标准输入,标准输出,标志错误,重定向到垃圾桶文件里,新的会话不再与终端关联int fd=open(nullfile.c_str(),O_RDWR);if(fd>0)//打开成功{dup2(fd,0);dup2(fd,1);dup2(fd,2);close(fd);}}
#pragma once#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include "Log.hpp"
#include "TASK.hpp"
#include "ThreadPool.hpp"
#include "Daemon.hpp"
Log lg;const std::string defaultip="0.0.0.0";
const int defaultfd=-1;
int backlog=10;//一般不要设置太大
enum 
{SockError=2,BindError,AcceptError,
};
class Tcpserver;class ThreadData
{
public:ThreadData(int &fd,const std::string& ip,uint16_t &port,Tcpserver* svr):_sockfd(fd),_ip(ip),_port(port),_svr(svr){}
public:  int _sockfd;std::string _ip;uint16_t _port;Tcpserver* _svr;
};class Tcpserver
{
public:Tcpserver(const uint16_t &port,const std::string &ip=defaultip):_listensock(-1),_port(port),_ip(ip){}void Init(){//服务器端启动之前创建套接字,绑定。//一开始的这个套接字是属于监听套接字_listensock=socket(AF_INET,SOCK_STREAM,0);if(_listensock<0){lg(Fatal,"sock create errno:%d errstring:%s",errno,strerror(errno));exit(SockError);}//创建套接字成功lg(Info,"sock create sucess listensock:%d",_listensock);int opt = 1;setsockopt(_listensock, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &opt, sizeof(opt)); // 防止偶发性的服务器无法进行立即重启(tcp协议的时候再说)//创建成功后就要绑定服务器的网络信息struct sockaddr_in local;memset(&local,0,sizeof(local));//填充信息local.sin_family=AF_INET;local.sin_port=htons(_port);inet_aton(_ip.c_str(),&local.sin_addr);//填充完毕,真正绑定if((bind(_listensock,(struct sockaddr*)&local,sizeof(local)))<0){lg(Fatal,"bind errno:%d errstring:%s",errno,strerror(errno));exit(BindError);}lg(Info,"bind socket success listensock:%d",_listensock);//绑定成功//udp中绑定成功后就可以进行通信了,但tcp与udp不同。tcp是面向连接的,在通信之前//需要先获取新连接,获取到新连接才能进行通信。没有获取连接那么就要等待连接,等待新连接的过程叫做监听,监听有没有新连接。//需要将套接字设置成监听状态listen(_listensock,backlog);//用来监听,等待新连接,只有具备监听状态才能识别到连}static void* Routine(void *args)//静态成员函数无法使用成员函数,再封装一个服务器对象{//子线程要和主线程分离,主线程不需要等待子线程,直接回去重新获取新连接pthread_detach(pthread_self());ThreadData* td=static_cast<ThreadData*>(args);//子线程用来服务客户端td->_svr->Service(td->_sockfd,td->_ip,td->_port);delete td;return nullptr;}void Run(){Daemon();signal(SIGPIPE,SIG_IGN);//防止服务端往一个已经关闭的文件描述符里写入,忽略带操作系统发送的信号//一启动服务器,就将线程池中的线程创建ThreadPool<TASK>::GetInstance()->Start();//单例对象//静态函数,通过类域就可以使用lg(Info,"tcpserver is running");while(true){struct sockaddr_in client;socklen_t len=sizeof(client);//将套接字设置成监听状态后,就可以获取新连接int sockfd=accept(_listensock,(struct sockaddr*)&client,&len);//获取从监听套接字那里监听到的连接。然后返回一个新套接字,通过这个套接字与连接直接通信,而监听套接字继续去监听。if(sockfd<0){lg(Fatal,"accept error,errno: %d, errstring: %s",errno,strerror(errno));exit(AcceptError);}//获取新连接成功//将客户端端网络信息带出来uint16_t clientport=ntohs(client.sin_port);char clientip[32];inet_ntop(AF_INET,&client.sin_addr,clientip,sizeof(clientip));//根据新连接进行通信lg(Info,"get a new link...sockfd: %d,clientip: %s,clientport: %d",sockfd,clientip,clientport);//构建任务TASK t(sockfd,clientip,clientport); //将任务放进线程池里,线程就会到线程池里去执行任务。ThreadPool<TASK>::GetInstance()->Push(t);}}void Service(int &sockfd,const std::string &clientip,uint16_t &clientport){char inbuffer[1024];while(true){ssize_t n=read(sockfd,inbuffer,sizeof(inbuffer));if(n>0){inbuffer[n]=0;std::cout<<"client say# "<<inbuffer<<std::endl;//加工处理一下std::string echo_string="tcpserver加工处理数据:";echo_string+=inbuffer;//将加工处理的数据发送会去write(sockfd,echo_string.c_str(),echo_string.size());}else if(n==0)//如果没有用户连接了,那么就会读到0.服务器端也就不要再读了{lg(Info,"%s:%d quit, server close sockfd: %d",clientip.c_str(),clientport,sockfd);break;}else{lg(Fatal,"read errno: %d, errstring: %s",errno,strerror(errno));}}}~Tcpserver(){}private:int _listensock;//监听套接字只有一个,监听套接字用来不断获取新的连接。返回新的套接字std::string _ip;uint16_t _port;
};
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>void Usage(std::string proc)
{std::cout<<"\n\rUsage: "<<proc<<" port[1024+]\n"<<std::endl;
}
//./tcpclient ip port
int main(int args,char* argv[])
{if(args!=3){Usage(argv[0]);exit(1);}std::string serverip=argv[1];uint16_t serverport = std::stoi(argv[2]);struct sockaddr_in server;socklen_t len=sizeof(server);server.sin_family=AF_INET;server.sin_port=htons(serverport);inet_pton(AF_INET,serverip.c_str(),&server.sin_addr);while(true){//创建套接字int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd<0){std::cout<<"create sockfd err "<<std::endl;}//创建套接字成功,创建完套接字后该干什么?//连接服务器端的套接字,所以客户端用户需要知道服务器端的网络信息的int cnt=10;bool isreconnect=false;do{ int n=connect(sockfd,(struct sockaddr*)&server,len);if(n<0)//服务器关闭了,肯定会连接失败{isreconnect=true;cnt--;std::cout<<"connect sock err...,cnt: "<<cnt<<std::endl;sleep(12);}else//重连成功了{break;}}while(cnt&&isreconnect);//连接成功//连接成功后,就可以直接通信了,就可以直接给对方写消息了。if(cnt==0){std::cerr<<"user offline.."<<std::endl;break;//用户直接不玩了}std::string message;std::cout<<"Please enter#";getline(std::cin,message);//往套接字里写int n=write(sockfd,message.c_str(),message.size());if(n<0)//服务器端会将该套接字关闭,然后就写不进去了。需要重新创建套接字连接{std::cerr<<"write error..."<<std::endl;continue;}char outbuffer[1024];//接收服务器发送的加工处理消息n=read(sockfd,outbuffer,sizeof(outbuffer));if(n>0){outbuffer[n]=0;std::cout<<outbuffer<<std::endl;}close(sockfd);}return 0;}

在这里插入图片描述

相关文章:

【Linux网络编程六】服务器守护进程化Daemon

【Linux网络编程六】服务器守护进程化Daemon 一.背景知识&#xff1a;前台与后台二.相关操作三.Linux的进程间关系四.自成会话五.守护进程四步骤六.服务器守护进程化 一.背景知识&#xff1a;前台与后台 核心知识就是一个用户在启动Linux时&#xff0c;都会给一个session会话&a…...

MySQL之json数据操作

1 MySQL之JSON数据 总所周知&#xff0c;mysql5.7以上提供了一种新的字段格式json&#xff0c;大概是mysql想把非关系型和关系型数据库一口通吃&#xff0c;所以推出了这种非常好用的格式&#xff0c;这样&#xff0c;我们的很多基于mongoDB的业务都可以用mysql去实现了。当然…...

【大厂AI课学习笔记】【2.1 人工智能项目开发规划与目标】(5)数据管理

今天学习了数据管理&#xff0c;以及数据管理和数据治理的区别和联系。 数据管理&#xff1a;利用计算机硬件和软件技术对数据进行有效的收集、存储、处理和应用的过程其目的在于充分有效地发挥数据的作用。 实现数据有效管理的关键是数据组织。 数据管理和数据治理的区别&am…...

Linux满载CPU和运行内存的方法

查询CPU详细信息命令如下&#xff1a; 查看物理CPU型号&#xff1a; cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c查看物理CPU个数 cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l查看每个物理CPU中core的个数(即核数) cat /proc/cpuinfo…...

每日五道java面试题之java基础篇(九)

目录&#xff1a; 第一题 你们项⽬如何排查JVM问题第二题 ⼀个对象从加载到JVM&#xff0c;再到被GC清除&#xff0c;都经历了什么过程&#xff1f;第三题 怎么确定⼀个对象到底是不是垃圾&#xff1f;第四题 JVM有哪些垃圾回收算法&#xff1f;第五题 什么是STW&#xff1f; 第…...

spring @Transactional注解参数详解

事物注解方式: Transactional 当标于类前时, 标示类中所有方法都进行事物处理 , 例子: 1 Transactional public class TestServiceBean implements TestService {}当类中某些方法不需要事物时: Transactional public class TestServiceBean implements TestService {private…...

D - 串结构练习——字符串连接

串结构练习——字符串连接 Description 给定两个字符串string1和string2&#xff0c;将字符串string2连接在string1的后面&#xff0c;并将连接后的字符串输出。 连接后字符串长度不超过110。 Input 输入包含多组数据&#xff0c;每组测试数据包含两行&#xff0c;第一行代表s…...

什么样的服务器是高性能服务器?

首先&#xff0c;高性能服务器应具备高处理能力。随着业务的不断扩展和数据量的爆炸性增长&#xff0c;高性能服务器需要具备强大的计算能力&#xff0c;能够快速处理各种复杂的业务和数据。这要求高性能服务器采用先进的处理器技术&#xff0c;如多核处理器、GPU加速等&#x…...

数学建模【线性规划】

一、线性规划简介 线性规划通俗讲就是“有限的资源中获取最大的收益”&#xff08;优化类问题&#xff09;。而且所有的变量关系式都是线性的&#xff0c;不存在x、指数函数、对数函数、反比例函数、三角函数等。此模型要优化的就是在一组线性约束条件下&#xff0c;求线性目标…...

ChatGPT的大致原理

国外有个博主写了一篇博文&#xff0c;名字叫TChatGPT: Explained to KidsQ」&#xff0c; 直译过来就是&#xff0c;给小孩子解释什么是ChatGPT。 因为现实是很多的小孩子已经可以用父母的手机版ChatGPT玩了 &#xff0c;ChatGPT几乎可以算得上无所不知&#xff0c;起码给小孩…...

蓝桥杯备赛_python_BFS搜索算法_刷题学习笔记

1 bfs广度优先搜索 1.1 是什么 1.2怎么实现 2案例学习 2.1.走迷宫 2.2.P1443 马的遍历 2.3. 九宫重排&#xff08;看答案学的&#xff0c;实在写不来&#xff09; 2.4.青蛙跳杯子&#xff08;学完九宫重排再做bingo&#xff09; 2.5. 长草 3.总结 1 bfs广度优先搜索 【P…...

轮播图的五种写法(原生、vue2、vue3、react类组件,react函数组件)

轮播图效果是一种在网页或应用程序中展示多张图片或内容的方式,通常以水平或垂直的方式循环播放。本文使用原生、vue2、vue3、react类组件,react函数组件五种写法实现了简单的轮播图效果,需要更多轮播效果需要再增加样式或者动画。 淡入淡出效果:每张图片渐渐淡入显示,然后…...

【MySQL】高度为2和3时B+树能够存储的记录数量的计算过程

文章目录 题目答案高度为2时的B树高度为3时的B树总结 GPT4 对话过程 题目 InnoDB主键索引的Btree在高度分别为 2 和 3 时&#xff0c;可以存储多少条记录&#xff1f; 答案 高度为2时的B树 计算过程&#xff1a; 使用公式 ( n 8 ( n 1 ) 6 16 1024 ) (n \times 8 …...

软件著作书 60页代码轻松搞定!(附exe和代码)

最近做了一个软件&#xff0c;准备去申请软件著作书&#xff0c;看着那60页的文档&#xff0c;确实难搞&#xff0c;不过幸好会用一点点python&#xff0c;就自己用python写了一个读取所有文件代码的程序&#xff0c;使用起来也很简单&#xff0c;过来分享一下 链接&#xff1…...

阿里文档类图像的智能识别,文档分类自定义分类器

阿里云文档类图像智能识别服务为用户提供了强大的文档处理能力&#xff0c;可以将文档图像中的文本内容、表格数据和结构化信息自动识别并提取出来。而自定义分类器则允许用户根据自己的需求&#xff0c;训练出更适合自己场景的文档分类模型。本文将详细介绍阿里云文档类图像智…...

256.【华为OD机试真题】会议室占用时间(区间合并算法-JavaPythonC++JS实现)

🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目二.解题思路三.题解代码Python题解代码JAVA题解…...

人工智能学习与实训笔记(三):神经网络之目标检测问题

人工智能专栏文章汇总&#xff1a;人工智能学习专栏文章汇总-CSDN博客 目录 三、目标检测问题 3.1 目标检测基础概念 3.1.1 边界框&#xff08;bounding box&#xff09; 3.1.2 锚框&#xff08;Anchor box&#xff09; 3.1.3 交并比 3.2 单阶段目标检测模型YOLOv3 3.2…...

SSM框架,Spring-ioc的学习(下)

拓展&#xff1a;在xml文件中读取外部配置文件 例&#xff1a;若要导入外部配置文件jdbc.properties <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"<http://www.springframework.org/schema/beans>"xmlns:xsi"&l…...

【AIGC】Stable Diffusion的模型微调

为什么要做模型微调 模型微调可以在现有模型的基础上&#xff0c;让AI懂得如何更精确生成/生成特定的风格、概念、角色、姿势、对象。Stable Diffusion 模型的微调方法通常依赖于您要微调的具体任务和数据。 下面是一个通用的微调过程的概述&#xff1a; 准备数据集&#xf…...

VNCTF 2024 Web方向 WP

Checkin 题目描述&#xff1a;Welcome to VNCTF 2024~ long time no see. 开题&#xff0c;是前端小游戏 源码里面发现一个16进制编码字符串 解码后是flag CutePath 题目描述&#xff1a;源自一次现实渗透 开题 当前页面没啥好看的&#xff0c;先爆破密码登录试试。爆破无果…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

算法—栈系列

一&#xff1a;删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...