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);
        }
    }
}
相关推荐
fangzhanpeng1686 天前
快速掌握C#语言基础知识点(1.基础数据类型)
开发语言·c#·1024程序员节
无己心9 天前
面向多平台 AI 搜索引擎的适配层架构设计
前端·人工智能·搜索引擎·ai·1024程序员节
u01030552715 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u01030552715 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝16 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u01030552717 天前
Java图像处理实战指南
人工智能·1024程序员节
u01030552717 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u01030552719 天前
Java实用类应用精讲
人工智能·1024程序员节
u01030552720 天前
Java I/O核心操作实战
人工智能·1024程序员节
u01030552721 天前
ArrayList操作详解与实战应用
人工智能·1024程序员节