【日志与守护进程】

news2024/11/24 14:26:12

文章目录

  • 1 :peach:日志:peach:
    • 1.1 :apple:对日志的基本理解:apple:
    • 1.2 :apple:对日志系统代码的基本编写:apple:
      • 1.2.1 :lemon:messageLog.hpp:lemon:
      • 1.2.2 :lemon:tcpServer:lemon:
    • 1.3 :lemon:验证:lemon:
  • 2 :peach:守护进程:peach:
    • 2.1 :apple:进程组与会话:apple:
    • 2.2 :apple:守护进程:apple:


1 🍑日志🍑

1.1 🍎对日志的基本理解🍎

在前面我们写tcp的CS模型中我们不难知道,每次出现了一些错误信息时我们都是将其打印在了终端上面,但是这种方式在实际中是不可取的,而我们就要将其中的信息记录在一个文件中方便我们查看,所以我们还得再加一个简单的日志(ps:博主这里写的日志是一个简易版本的日志系统,实际上如果想完成一个较为完整的日志系统比这里难度要大得多)而日志中的信息我们也习惯将其分一下类:

enum
{
    Debug = 0,
    Infor,
    Warnning,
    Error,
    Fatal,
    Unkonwn
};

各种信息的命名顾名思义,有了这个理解后我们再来编写代码就会轻松得多。

1.2 🍎对日志系统代码的基本编写🍎

1.2.1 🍋messageLog.hpp🍋

#pragma once

#include <string>
#include <sys/types.h>
#include <unistd.h>
#include<cstdio>
#include <stdarg.h>
#include<ctime>


#include "err.hpp"
using namespace std;

const char* logname="log.txt";

static string GetLev(int lev)
{
    switch(lev)
    {
        case 0:
        return "Debug";
        case 1:
        return "Infor";
        case 2:
        return "Warnning";
        case 3:
        return "Error";
        case 4:
        return "Fatal";
        default:
        return "Unkonwn";
    }
}

static string GetTime()
{
        //        struct tm {
        //        int tm_sec;         /* seconds */
        //        int tm_min;         /* minutes */
        //        int tm_hour;        /* hours */
        //        int tm_mday;        /* day of the month */
        //        int tm_mon;         /* month */
        //        int tm_year;        /* year */
        //        int tm_wday;        /* day of the week */
        //        int tm_yday;        /* day in the year */
        //        int tm_isdst;       /* daylight saving time */
        //    };

    time_t cur=time(nullptr);
    tm* pt=localtime(&cur);
    char buffer[1024]={0};
    snprintf(buffer,sizeof(buffer),"%d-%d-%d:%d:%d:%d",pt->tm_year+1900,pt->tm_mon+1,
                pt->tm_mday,pt->tm_hour,pt->tm_min,pt->tm_sec);

    return buffer;

}

void LogMessage(int level, const char *format, ...)
{
    char Llog[1024] = {0}; // 记录一些基本的日志消息
    string lev = GetLev(level);
    string time = GetTime();
    snprintf(Llog, sizeof(Llog), "[%s] [%s] [%d] ", lev.c_str(), time.c_str(), getpid());

    char Rlog[1024]={0};//记录用户添加的信息,可以让用户自行调整
    va_list p;
    va_start(p,format);
    vsnprintf(Rlog,sizeof(Rlog),format,p);
    va_end(p);

    //将日志信息保存在文件中
    FILE* fp=fopen(logname,"a");
    if(fp==nullptr)
        exit(-1);
    fprintf(fp,"%s%s\n",Llog,Rlog);
    fclose(fp);
}

代码中其他地方还好,这里博主主要讲解下在LogMessage接口中使用的可变参数列表,大家可以简单的这么理解下面的这些:

      va_list p; // char *
      int a = va_arg(p, int);  // 根据类型提取参数
      va_start(p, format); //p指向可变参数部分的起始地址
      va_end(p); // p = NULL;

然后再回去看上面的代码就会轻松很多了。

1.2.2 🍋tcpServer🍋

这里就只列举一部分的样例, 其余部分也是同理:
在这里插入图片描述

1.3 🍋验证🍋

在这里插入图片描述不难发现已经验证成功了。

想要了解更多关于日志系统的介绍与实现可以参考博主另外的一篇文章:
【日志系统】


2 🍑守护进程🍑

2.1 🍎进程组与会话🍎

在讲解守护进程前我们先来了解下进程组,会话的基本理解。
首先我们创建2个前台进程:

 sleep 1000 | sleep 2000

在这里插入图片描述然后还是在该界面上再创建2个后台进程:

sleep 1000 | sleep 2000 &

在这里插入图片描述从上面的图中我们了解过PPID PID,而PGID和SID就是我们马上要讲解的进程组和会话。从上面的图中我们不难发现,进程组有3个,进程会话只有两个,我们刚创建的6个进程都隶属于同一个会话,会话中又包含了两个进程组,所以我们不难得出下面的关系:

会话>=进程组>=进程

而进程组的组长就是我们第一个创建的进程,从上面图中我们也可以很好的得到验证.
我们可以查看4853进程是哪一个?
在这里插入图片描述验证得知是bash进程。

像上面我们创建一个新的页面就会打开一个新的会话,会话中有着很多任务(进程组).

我们可以使用jobs来查看进程组以及任务号。比如我们再创建几个后台进程:
在这里插入图片描述其中第一列上面的数字就叫做任务编号。
在这里插入图片描述那假如我们想让某一个任务从后台进程变成前台进程呢?我们可以使用fg命令:
在这里插入图片描述
当我们使用了fg命令将3号任务变成前台进程时,我们发现该终端已经不能够再显示命令提示符了(也就是bash不能够运行了),为什么呢?
因为一个会话中只能有一个前台进程在运行,而当前该会话中已经有了3号进程在运行,所以自然bash就不能够正常运行了,当我们把该进程Ctrl+C时:
在这里插入图片描述
bash又能够正常运行了。

那我们并不想让后台进程变成前台进程呢?我们可以使用Ctrl+Z,然后再用bg命令来继续让后台命令运行:
在这里插入图片描述

所以我们不难得出结论:登录就是创建一个会话,bash任务会启动我们创建的进程,也就是在当前会话中创建新的任务;那么当我们退出登录是就要销毁该会话中所有的任务。

所以我们在实现TCP服务器的时候,我们应该让服务器拥有独立的会话,否则的话当我们关闭了服务器后就不能够正常服务了。

2.2 🍎守护进程🍎

那么我们应该怎样让普通进程变成守护进程呢?
最主要的接口就是setsid.
在这里插入图片描述其实系统也给我们提供了daemon接口,但是我们不使用这个接口,而是自己手动写一个守护进程。

daemon.hpp:

#pragma once

#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<cstring>
#include<cstdlib>

#include "messageLog.hpp"
#include"err.hpp"

void Daemon()
{
    // 1 忽略信号
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);

    // 2 让自己不要成为组长(守护进程不能够是组长)
    if (fork() > 0)
        exit(0);

    // 3. 新建会话,自己成为会话的话首进程
    pid_t ret = setsid();
    if ((int)ret == -1)
    {
        LogMessage(Fatal, "deamon error, code: %d, string: %s", errno, strerror(errno));
        exit(SETSID_ERR);
    }
    // 4. 可选:可以更改守护进程的工作路径
    // chdir("/")
    
    // 5. 处理后续的对于0,1,2的问题
    int fd = open("/dev/null", O_RDWR);
    if (fd < 0)
    {
        LogMessage(Fatal, "open error, code: %d, string: %s", errno, strerror(errno));
        exit(OPEN_ERR);
    }
    dup2(fd, 0);
    dup2(fd, 1);
    dup2(fd, 2);
    close(fd);
}

其中代码中的每一步我都给予了详细的说明,这里需要额外讲解下的就是/dev/null,大家可以把这个文件理解为一个黑洞,就是可以把你的任何数据都丢到里面,但是不会给你保存,丢进去了就找不到了。

此时我们来验证下:
在这里插入图片描述当我们运行时我们发现并不会像以前那样卡在那里等待着客户端,其实这个很好理解,因为该进程已经成为了守护进程,已经有了独立会话所以自然不会显现。
我们可以查询一下该进程;
在这里插入图片描述我们使用客户端来访问时:
在这里插入图片描述不难发现也是成功了的。

但是这时大家或许会问了,那你这样不是无敌了嘛,那我想干掉守护进程咋办?其实大家不要担心,杀人不眨眼的kill -9可以直接干掉守护进程。
在这里插入图片描述到目前为止,守护进程的工作已经做得差不多了。

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

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

相关文章

Rabbitmq 的管理配置

1、Rabbitmq管理 1.1、多租户与权限 每一个RabbitMQ 服务器都能创建虚拟的消息服务器&#xff0c;我们称之为虚拟主机(virtual host) ,简称为vhost 。每一个vhost 本质上是一个独立的小型RabbitMQ 服务器&#xff0c;拥有自己独立的队列、交换器及绑定关系等&#xff0c;井且它…

用PHP爬取视频代码示例详细教程

以下是一个使用Symfony Panther和PHP进行爬虫的示例程序&#xff0c;用于爬虫企鹅上的视频。请注意&#xff0c;这个示例需要使用https://www.duoip.cn/get_proxy这段代码获取爬虫IP。 <?php // 引入所需的库 require vendor/autoload.php;use Symfony\Component\Panther\P…

多媒体应用设计师 第7章 多媒体数字压缩编码技术基础

1.多媒体数据压缩技术理论基础及压缩编码方法分类 必要性:大数据量的图像信息会给存储器的存储容量&#xff0c;通信线路的带宽&#xff0c;以及计算机的处理速度增加极大压力。如果没有多媒体编码压缩技术的发展&#xff0c;大容量图像&#xff0c;视频信息的存储和传输就难以…

林旅强 | AI+开源时代 - 开发者与治理者的机遇与挑战

点击以下链接收听本期 “大咖访谈” 播客&#xff0c;与大咖面对面&#xff1a; 大咖访谈链接&#xff1a;EP15&#xff1a;林旅强 | AI开源时代 - 开发者与治理者的机遇与挑战 刘天栋&#xff1a;访谈主持&#xff0c;开源雨林顾问&#xff0c;开源社联合创始人&#xff0c;Ap…

人工智能应该怎么学?

人工智能这个词炙手可热&#xff0c;为了跟上时代的步伐&#xff0c;有许多小伙伴就想学习人工智能&#xff0c;今天来介绍一下人工智能究竟是什么&#xff1f;应该怎么学&#xff1f;怎么入门&#xff1f; 首先来看一下什么是人工智能&#xff1f; 人工智能 人工智能 人工智能…

puppeteer学习笔记

目录 介绍启动方法功能一、爬虫优势如何实现爬虫小demo 功能二、执行脚本百度搜索脚本demo 功能三、获取cookie&#xff08;这个只能是模拟浏览器当前进入网页的cookie不是平时用的下载的的浏览器的cookie&#xff09;功能四、监控网页&#xff0c;进行性能分析 介绍 puppetee…

文旅部发布《旅游电子合同管理与服务规范》,推动旅游企业转型升级

日前&#xff0c;文化和旅游部批准发布了旅游电子合同领域的行业标准《旅游电子合同管理与服务规范》&#xff08;以下简称《标准》&#xff09;&#xff0c;将于2023年12月9日起实施。 《标准》聚焦旅游电子合同的适用范围、基本要素、操作规范、载体要求、安全保密等方面进…

【编译原理】对++*p++操作理解

目录 1. 代码段执行结果 2. *p的结合过程 3. 通过汇编代码判断执行结果 1. 代码段执行结果 对于以下代码&#xff1a; int main() { int i 0;int *p &i; *p ; return i; }输出结果为&#xff1a; ASM generation compiler returned: 0 Execution build compiler re…

隐写术--python隐写

0x00 背景 何为隐写术&#xff1f; 隐写术是一类可以隐藏自己写的一些东西的方法&#xff0c;是一门关于信息隐藏的技巧与科学。指的是采取一些不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容的方法。 可参考 一文让你完全弄懂Stegosaurus - 知乎 本文要…

机械设计中的结构要素、基本要求和准则

机械结构设计的任务是依据设计任务在总体设计构想的基础上&#xff0c;确定的原理方案&#xff0c;绘制出具体的结构图&#xff0c;以实现设计所要求的功能。设计的过程是将抽象的工作原理具体化为某类构件或零部件&#xff0c;包含确定结构件的材料、形状、尺寸、公差、热处理…

机器学习绪论

目录 第1关&#xff1a;什么是机器学习 相关知识 题目答案 第2关&#xff1a;机器学习的常见术语 相关知识 假设空间 归纳偏好 题目答案 第3关&#xff1a;机器学习的主要任务 相关知识 分类 回归 聚类 题目答案 第1关&#xff1a;什么是机器学习 相关知识 相信…

给你一个文件夹,统计其下面的文件数量,包括子文件夹下面的文件

对于统计一个文件夹下面的文件的数量&#xff0c;大家第一反应肯定是递归调用来实现&#xff0c;现在有这么一个目录结构&#xff1a;root1和root2下面各有一个文件file1.txt和file2.txt&#xff0c;所以最终统计出来的文件数量应该是3 我们先看看递归实现&#xff1a; public …

Plant Commun | 正交组、系统转录组和CUT-Tag发掘植物保守冷响应因子BBX29及其靶基因

植物以固着的方式生活&#xff0c;但它们并不完全被动&#xff0c;许多温带植物通过预暴露于非冻结低温来增加它们的抗冻性&#xff0c;这种适应性过程被称为冷驯化(CA)。越来越多的证据表明&#xff0c;低温下的许多生理和代谢变化是由于CA诱导的冷反应(COR)基因的表达。C-重复…

Android 远程调用服务之 AIDL

目录 一、AIDL 是什么&#xff1f;二、为什么要使用 AIDL&#xff1f; 1、使用 AIDL 是为了跨进程调用第三方服务&#xff1f; 2、使用 AIDL 是为了向第三方服务传输数据/参数&#xff1f; 3、使用 AIDL 是为了获取第三方服务直接或者异步返回的数据&#xff1f;三…

Linux性能优化--性能工具:磁盘I/O

6.0 概述 本章介绍的性能工具能帮助你评估磁盘I/O子系统的使用情况。这些工具可以展示哪些磁盘或分区已被使用&#xff0c;每个磁盘处理了多少I/O,发给这些磁盘的I/O请求要等多久才被处理。 阅读本章后&#xff0c;你将能够&#xff1a; 确定系统内磁盘I/O的总量和类型(读/写…

浅谈智能照明控制系统应用在城市轨道交通

叶根胜 江苏安科瑞电器制造有限公司 江苏江阴 214405 摘要&#xff1a;在传统的城市轨道交通设计方面&#xff0c;照明设计方案具有一定的弊端。随着计算机技术的发展&#xff0c;智能化技术渐渐步入人们的生活并成为主流&#xff0c;故在城市轨道交通中应用新型的照明控制设…

基于关联规则的多样化推荐技术应用研究

摘要 目录 第二章 相关理论介绍 2.2.1 当前常用推荐技术 关联规则推荐 2.3.1 关联规则相关概念

【java学习—七】Object类(36)

文章目录 1. 概念2. Object类中的主要方法 1. 概念 Object 类是所有 Java 类的根父类如果在类的声明中未使用 extends 关键字指明其父类&#xff0c;则默认父类为Object 类 public class Person {...}等价于&#xff1a;public class Person extends Object {...}例&#xff1…