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

【Linux】:守护进程化

朋友们、伙计们,我们又见面了,本期来给大家带来守护进程相关的知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

​ 

目录

1. 守护进程

1.1 进程组与会话

2. 实现守护进程


1. 守护进程

我们之前实现的网络服务(udp、tcp)不能直接在bash中以前台进程的方式直接运行,真正的服务器必须在Linux后台以守护进程(精灵进程)的方式运行!不受用户登陆和注销的影响

1.1 进程组与会话

在实现守护进程之前我们先来了解一组概念:

进程组、会话、作业

我们可以在bash启动一条命令来看一下这组概念:

同样的我们也可以查看一下bash的进程组与会话:

所以通过上面的例子就可以看出来:

  • PID == PGID是自成一个进程组,并且进程组默认一定是在一个会话中的;
  • bash是自成进程组,自成会话

那么如果我们同时启动多个进程呢:

  • 同时启动多个进程时,这些进程是可以属于一个进程组的,组ID一般是第一个进程组ID
  • 每次我们登录Linux时,OS都会给我们提供一个bash,然后提供一个终端,为我们提供解析命令行服务,这些都叫做一个会话;
  • 在命令行启动的所有进程,最终默认都是在当前会话内部的一个进程组(也可以是一个进程一个进程组)。  

通过结合我们之前在信号部分提到的前台进程与后台进程可以得出一个结论:

  • 任何时刻,一个会话内部,可以以有多个进程组(用户级任务),但是默认任何时刻,都只允许一个进程组在前台(前台进程组)
  • 会话和会话之前是具有隔离性的

在命令行启动命令时只需要在后面加上 & 既可以将其以后台进程的方式启动;

使用jobs可以查看当前会话的进程组:

我们已经运行起来的进程可以使用ctrl + z来停止然后将其放到后台:

通过fg + 任务编号可以将指定的任务放到前台:

通过bg + 任务编号可以将指定的任务在后台运行起来:

这些命令在前面的部分都已经提到过了,这里就不做过多解释了; 

2. 实现守护进程

结合进程组和会话的概念,守护进程其实就是一个独立的会话,不隶属于任何一个bash的会话:

实现守护进程的接口是:

他有一个前提条件是:

调用他的进程不能是一个进程组的组长,但是多个进程中,第一个是组长,单进程中自己也是组长,所以要实现守护进程,就必须要创建子进程,然后直接关闭父进程,此时的子进程就可以成为守护进程,换句话说,守护进程其实就是孤儿进程; 

实现守护进程一般分为五步:

  • ① 忽略可能引起进程异常退出的信号
  • ② 让自己不要成为组长(fork)
  • ③ 使用setsid接口;
  • ④ 是否将自己的当前目录(CWD)更改为根目录(为了方便以根目录直接查找各种资源)
  • ⑤ 是否需要关联用户的输入输出以及错误信息

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
    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);
        }
    }
}

Main.cc:

#include "Daemon.hpp"
#include <unistd.h>

int main()
{
    // 变成守护进程
    Daemon(true, false);
    // 需要执行的核心代码
    while (1)
    {
        sleep(1);
    }
    return 0;
}

测试结果:

同样的我们也可以对我们之前实现的udp和tcp代码进行守护进程化,在初始化之前将程序设置为守护进程即可:

tcp守护进程化源码:

https://gitee.com/yue-sir-bit/linux/tree/master/4.tcp_server_echo

相关文章:

  • 工具层handle_excel
  • Java-泛型总结
  • 蓝桥杯备考:奶牛晒衣服
  • Android NDK --- JNI从入门到基础的全面掌握 (上)
  • github上传本地文件到远程仓库(空仓库/已有文件的仓库)
  • python环境集成整理
  • Linux动态库和静态库
  • RAGFlow + LlamaIndex 本地知识库RAG增强架构与实现直播智能复盘
  • 【入门初级篇】布局类组件的使用(1)
  • 如何通过Python实现自动化任务:从入门到实践
  • 2025年 cocosCreator 1.8 定制 JavaScript 引擎
  • Web Component 教程(五):从 Lit-html 到 LitElement,简化组件开发
  • 用css绘制收银键盘
  • 实验三 内存管理
  • RocketMQ 架构
  • std::move
  • Unity3D开发AI桌面精灵/宠物系列 【二】 语音唤醒 ivw 的两种方式-Windows本地或第三方讯飞等
  • 一些常用的docker镜像及命令 python各版本(持续更新中)
  • pnpm config set ignore-workspace-root-check true
  • 【Spring Boot 中 `@Value` 注解的使用】
  • 柳州警方通报临牌车撞倒行人:扣留涉事车辆,行人无生命危险
  • 在上海生活8年,13岁英国女孩把城市记忆写进歌里
  • 哈马斯官员:只要以军持续占领,哈马斯就不会放下武器
  • 怎样更加贴近中国消费者,运动品牌给出“本地化”选择
  • 保时捷中国研发中心落户上海虹桥商务区,计划下半年投入运营
  • 大家聊中国式现代化|邓智团:践行人民城市理念,开创人民城市建设新局面