Linux——守护进程

1、进程组

1-1****什么是进程组

之前我们提到了进程的概念, 其实每一个进程除了有一个进程 ID(PID) 之外 还属于一
个进程组。 进程组是 一个 或者 多个 进程的集合, 一个进程组可以包含多个进程。 每一
个进程组也有一个唯一的进程组 ID(PGID) , 并且这个 PGID 类似于进程 ID , 同样是
一个正整数, 可以存放在 pid_t 数据类型中。

bash 复制代码
$ ps -eo pid,pgid,ppid,comm | grep test

-e 选项表示 every 的意思, 表示输出每一个进程信息

-o 选项以逗号操作符(,)作为定界符, 可以指定要输出的列

1-2 组长进程

每一个进程组都有一个组长进程。 组长进程的 ID 等于其进程 ID。我们可以通过 ps 命 令看到组长进程的现象

从结果上看 ps 进程的 PID 和 PGID 相同, 那也就是说明 ps 进程是该进程组的组长进 程, 该进程组包括 ps 和 cat 两个进程

进程组组长的作用:

进程组组长可以创建一个进程组或者创建该组中的进程

进程组的生命周期: 从进程组创建开始到其中最后一个进程离开为止。

注意: 主要某个进程组中有一个进程存在, 则该进程组就存在, 这与其组长进程是否已经终 止无关。

2、会话&&控制终端

前面写的服务器是不是直接这样跑起来就行了?

并不是,cal_server真正想要在服务器上跑是要变成守护进程的

变成守护进程的做法

命令行式

复制代码
nohup ./cal_server 8888 1>/dev/null 2>/dev/null &

此时我们的进程已经变成类似于守护进程的东西了,但是严格意义上还不算守护进程

此时进程已经在后台上跑了

cpp 复制代码
ps axj | grep cal_server

用client发送请求也有响应

现在就算把Xshell全关了这个服务还是会在服务器上跑

当我们登录机器时,Linux服务器会做两件事

1.打开一个终端文件(以下这种窗口)

开启几个窗口/dev/pts就会多出几个终端文件

2.新启动一个bash进程来给我们进行命令行解释

关掉后只剩一个

TTY显示的是和哪个终端文件相关联

在一个终端文件打开进程,可以看到它们的PPID、PID、PGID都不一样,说明他们两个是独立的,属于不同的进程组。

又可以看到他们的SID、TTY是一样的。tty说明了他们俩往同一个终端文件中打印,sid竟然就是bash所对应的会话。

在Linux中将以上过程打包起来总结为一个内容------新建会话

新开一个窗口(打开一个会话)

新启动一个bash进程

会话也有标识符------会话id

会话id一般都是会话中的第一个进程bash------话首进程

在一个会话中新启动的任何任务,比如上面的cal_server,在新启动的时候,一定是默认属于该会话的。

那么问题来了:关闭会话(窗口)会不会连带着其中的任务一起关闭呢?·会的,原则上我们要关闭时会话的内容会被全部释放,会话相当于Linux服务器对各个任务的一个管理容器

这会导致一种结果------服务器因为会话的关闭而退出或者出现自定义行为

小知识:windows中每次登录都会建一个会话(桌面),注销就是关闭会话

如何保证一个服务无论会话怎么退出,该服务都能够一直运行。

把进程单独拎出来生成一个新的会话就可以了

setid

复制代码
pid_t setsid(void);

创建一个新的会话,但是调此函数的进程不能是进程组的组长

如何解决?

cpp 复制代码
//父进程
if(fork()>0)
{
    exit(0);
}
setsid();

fork()后(子进程)一定不是组长;守护/精灵进程------也是一种孤儿进程

自己写代码可以将进程变为守护进程,也可以调用系统调用接口daemon直接一步到位,把那些fork、setsid啥的全做了

man daemon

cpp 复制代码
#include <unistd.h>
int daemon(int nochdir, int noclose);

nochdir:要不要更改当前进程的工作目录

要:切换成根目录/

不要:进程启动所在的路径

守护进程一般都要与自己的终端文件相关联,有的进程变成守护进程进入后台后不用关联终端文件

这时候还向终端文件去写就会出现问题。

noclose:是否需要进行输入输出的处理

0(标准输入)、1(标准输出)、2(标准错误)重定向到 /dev/null当中

相当于把代码的所有输入输出全部丢弃

返回值:成功返回0,失败返回-1

cpp 复制代码
#include <iostream>
#include<unistd.h>
using namespace std;
int main()
{
    cout<<"pid is:"<<getpid()<<endl;
    sleep(1);
    daemon(0,0);
    //执行下面代码的不是当前进程,而是当前进程的子进程
    while (true)
    {
        cout<<"hello"<<endl;
        sleep(1);
    }
    return 0;
    
}

程序还在后台跑,此时的pid会比原来的大一,因为是子进程在执行,而父进程在daemon时就已经退出了,会话ID此时也是自己的,和任何一个bash进程都不一样。这时就算关闭Xshell它还会在你的云服务器上跑

cpp 复制代码
ls /proc//111417 -l

工作目录此时改为根目录

输入输出也被重定向到dev/null

daemon(0,0)表示要更改工作目录、要重定向输入输出

而daemon(1,!)表示不更改工作目录,不重定向输入输出

3、作业控制

3-1什么是作业(job)和作业控制(Job Control)?

作业是针对用户来讲,用户完成某项任务而启动的进程,一个作业既可以只包含 一个进程,也可以包含多个进程,进程之间互相协作完成任务, 通常是一个进程 管道。

Shell 分前后台来控制的不是进程而是作业 或者进程组。一个前台作业可以由多 个进程组成,一个后台作业也可以由多个进程组成,Shell 可以同时运⾏一个前台 作业和任意多个后台作业,这称为作业控制。

下面的进程组就可以看作一个作用作业号是[1]

在写一个

放在后台执行的程序或命令称为后台命令,可以在命令的后面加上&符号从而让 Shell 识别这是一个后台命令,后台命令不用等待该命令执⾏完成,就可立即接收 新的命令,另外后台进程执行完后会返回一个作业号以及一个进程号(PID)

  • : 表示该作业号是默认作业

-:表示该作业即将成为默认作业

无符号: 表示其他作业

想要把作业放在前台可以用fg 作业号

此时作业跑到前台了

如何放到后台呢?要先把作业暂停,Linux不允许一个暂停状态的进程处在前台(前台进程跟用户的键盘输入有关,如果暂停了还在前台键盘输入无效果系统不就卡死了)

ctrl +Z就暂停跑后台去了

bg 作业号就可以启动进程了

4、守护进程

Daemon.hpp

cpp 复制代码
#pragma once
#include <iostream>
#include <string>
#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.fork,让自己不要成为组长
    if (fork() > 0)
        exit(0);
    // 3.setsid
    setsid();

    // 4.确认是否更改工作目录
    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);
        }
    }
}
相关推荐
海梨花4 小时前
【力扣Hot100】刷题日记
算法·leetcode·1024程序员节
生莫甲鲁浪戴4 小时前
Android Studio新手开发第三十一天
android studio·1024程序员节
Dev7z4 小时前
基于Swin Transformer的宠物皮肤病诊断系统
1024程序员节
王老师青少年编程5 小时前
AtCoder真题及详细题解 ABC427C: Bipartize
c++·题解·1024程序员节·atcoder·csp·abc·信奥赛
gAlAxy...5 小时前
面试JAVASE基础(五)——Java 集合体系
java·python·面试·1024程序员节
B站计算机毕业设计之家5 小时前
计算机视觉python口罩实时检测识别系统 YOLOv8模型 PyTorch 和PySide6界面 opencv (建议收藏)✅
python·深度学习·opencv·计算机视觉·cnn·1024程序员节
大肘子咒你5 小时前
数字狂潮来袭
数据结构·c++·1024程序员节
Lethehong5 小时前
首个多院区异构多活容灾架构,浙人医创新开新篇
1024程序员节·kingbasees
呆呆的猫6 小时前
【多模态】46、DeepSeek-OCR | 一张图片是否真能抵千词
ocr·1024程序员节