【Linux系统化学习】守护进程 | 序列化和反序列化

2024-05-13 22:04

本文主要是介绍【Linux系统化学习】守护进程 | 序列化和反序列化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

前言

守护进程

会话

进程组

setsid系统调用

守护进程系统调用

再谈协议

序列化和反序列化

Json


前言

上两篇文章我们所编写的服务器,并算不上真正意义上的服务器一般的服务器都是要随时能够访问的,就像我们在任何时间段都可以打开抖音获取视频资源;要想实现只需要将我们的进程变成守护进程(精灵进程)。

守护进程

会话

当我们使用xshell登录我们自己的服务器时操作系统会给登录用户提供:

  1. 命令行解释器(bash)
  2. 提供一个终端(给用户提供命令解析服务)

这个终端就是会话

进程组

当我们在同时运行多个进程时,shell就会将这几个进程归为一个组即进程组;因此进程组是一组相关联进程的集合,并且每一个进程组的第一个进程的ID为进程组ID。当只有一个进程启动的时候称为自成进程组。

前面说过任何时刻一个会话内部,可以包含很多进程组,但是默认时刻只允许一个进程组在前台也就是前台进程。当运行我们的服务器时,就是这种前台进程的状态;但是当我们退出xshell时,进程也就随之终止,被释放资源了;达不到一直运行的状态;因此我们可以将我们的进程转化为守护进程。

setsid系统调用

setsid 执行以下操作:

  1. 创建新的会话:它创建了一个新的会话,与当前的终端会话分离开来。这意味着即使当前的终端关闭,该会话也会继续存在。

  2. 设置当前进程为会话领导者setsid 将当前进程的进程ID设置为新会话的领导者(session leader)。这意味着当前进程成为了新会话中的第一个进程,并且没有父进程。

  3. 脱离终端:因为新的会话已经创建,setsid 将当前进程从其原始的控制终端分离开来。这样即使启动进程的终端关闭,该进程也不会受到影响。

但是单个的自成进程组是不可以调用这个系统调用的,因此我们可以创建子进程后父进程直接退出,让1号进程领养子进程,在子进程中调用这个系统调用。

Daemon.hpp

#pragma once#include <iostream>
#include <cstdlib>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>const char *root = "/";
const char *dev_null = "/dev/null";void Daemon(bool ischdir, bool isclose)
{// 1. 忽略可能引起程序异常退出的信号signal(SIGCHLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);// 2. 让自己不要成为组长if (fork() > 0)exit(0);// 3. 设置让自己成为一个新的会话, 后面的代码其实是子进程在走setsid();// 4. 每一个进程都有自己的CWD,是否将当前进程的CWD更改成为 / 根目录if (ischdir)chdir(root);// 5. 已经变成守护进程啦,不需要和用户的输入输出,错误进行关联了if (isclose){close(0);close(1);close(2);}else{// 这里一般建议就用这种int fd = open(dev_null, O_RDWR);if (fd > 0){dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}}
}

 注:

  • 要忽略可能引起进程异常终止的信号
  • 不可以使用三个标准IO流
  • 将标准IO流重定向,或者写入到系统的dev_null特殊文件中,IO对于这个文件都没有用

守护进程系统调用

上面的是我们通过系统调用setsid自主 实现的一种守护进程的方式,在系统中有直接的创建守护进程的系统调用。

int daemon(int nochdir, int noclose);

参数

  • nochdir:如果为非零值,表示不改变当前工作目录为根目录(/)。如果为零,表示将当前工作目录改变为根目录。
  • noclose:如果为非零值,表示不关闭标准输入、标准输出和标准错误文件描述符。如果为零,表示关闭这些文件描述符。

返回值

  • 如果成功,返回 0。
  • 如果失败,返回 -1,并设置 errno。

工作原理

  • 首先,daemon 函数会调用 fork 来创建一个子进程。
  • 子进程会调用 setsid 来创建一个新的会话,并成为该会话的领导者。
  • 如果 nochdir 参数为零,子进程会将当前工作目录更改为根目录(/)。
  • 如果 noclose 参数为零,子进程会关闭标准输入、标准输出和标准错误文件描述符。
  • 最后,子进程会返回 0,然后父进程退出。

 工作原理和我们上面自主实现的工作原理一模一样。

再谈协议

前面的文章我们简单说过协议就是对于通信双方来说就一种商量好的约定;但是socket api的接口都是按照”字符串“的方式来发送和接受的,如果我们要传送结构化的数据怎么办。

例如:如我们今天想制作一个网络版本的计算器;作为客户端来说我们要发送的是两个操作数和一个操作符,作为接收端我们收到的数据也是两个操作数和一个操作符,将发来的数据进行处理后;服务端我们是不是要发送运算结果和运算状态,在发送给客户端。

通过上面的例子我们可以将接收和发送的数据,设计为一个结构体;将这个结构体作为传输的基本数据结构,让客户端和服务端通信双方都遵守这个规则即可,这就是协议;

序列化和反序列化

在网络部分开始的时候我们就提到过TCP协议是面向字节流的,如果今天我们要使用TCP协议通信传输结构化的数据来实现上面的网络版本计算机,会遇到很多问题。

  • 对于语言来说,如果通信双方是使用不同的语言来编写的;对于不同的语言结构体定义和使用都不同;
  • 对于平台来说:结构体含有内存对齐,不同编译器和不同平台对结构体的内存布局可能有所不同,这可能导致在通信过程中出现数据的错位或填充。
  • 对于协议来说:TCP协议是面向字节节流的,如果只能发固定的字节,而这个固定的字节却不能支持一个完整的结构体,对于服务端来说如何处理不完整的数据

基于上面的问题,作为客户端就要将定义好的结构化数据转化为”字符串“字节流,这个过程就是序列化。

作为服务端我们收到的是”字符串“字节流,我们要将这个字节流转化为通信双方约定好的结构化数据,这个过程就是反序列化。

Json

简单来说序列化和反序列化就是将要发送的数据转化为字符串,将接收的数据转化为结构化的数据。也就是对字符串进行操作,如果我们自己实现这个过程,很麻烦也很容易出错;我们可以使用Json、protobuff、xml用来代替我们自主实现繁琐的字符转换。

注意:

  • TCP协议是全双工的,并且作为服务器和客户端双方是对等的;都可以进行收发消息。
  • 应用层用户通过write、send或者read、recv进行收发消息时只是将消息拷贝到内核TCP协议发送或者接收的缓冲区中、由协议决定缓冲区中的数据什么时候发送、发送多少、出错了怎么办;哪些函数只是拷贝函数。
  • TCP实际通信的时候其实是双方操作系统之间进行通信
  • 在用户层面你认为你发送了多少字节,但是对方比一定就要收多少字节
  • 自主实现协议的时候一定要明确字节流和字节流之间的边界,确保接收端读到完整的一个字节流
  • 生产者消费者模型的一种,任意一方向网络中放数据,一方从网络中取数据

今天对Linux中守护进程、序列化和反序列化的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!! 

这篇关于【Linux系统化学习】守护进程 | 序列化和反序列化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/986947

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss