【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

相关文章

如何配置Spring Boot中的Jackson序列化

《如何配置SpringBoot中的Jackson序列化》在开发基于SpringBoot的应用程序时,Jackson是默认的JSON序列化和反序列化工具,本文将详细介绍如何在SpringBoot中配置... 目录配置Spring Boot中的Jackson序列化1. 为什么需要自定义Jackson配置?2.

Linux ls命令操作详解

《Linuxls命令操作详解》通过ls命令,我们可以查看指定目录下的文件和子目录,并结合不同的选项获取详细的文件信息,如权限、大小、修改时间等,:本文主要介绍Linuxls命令详解,需要的朋友可... 目录1. 命令简介2. 命令的基本语法和用法2.1 语法格式2.2 使用示例2.2.1 列出当前目录下的文

Linux中的计划任务(crontab)使用方式

《Linux中的计划任务(crontab)使用方式》:本文主要介绍Linux中的计划任务(crontab)使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、前言1、linux的起源与发展2、什么是计划任务(crontab)二、crontab基础1、cro

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

Linux安装MySQL的教程

《Linux安装MySQL的教程》:本文主要介绍Linux安装MySQL的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux安装mysql1.Mysql官网2.我的存放路径3.解压mysql文件到当前目录4.重命名一下5.创建mysql用户组和用户并修