完整代码:https://gitee.com/tgwTTT/linux-learning-dai/blob/master/netCal

前言:在上篇文章作者通过网络计算器(http://www.tgwttt.xyz/?p=368)讲解了自定义协议,但是我们还缺少一个东西,试想当我们登录一个linux用户时,当将程序跑起来,但是当我们关闭用户时,我们挂在后台运行的服务器会不会受到影响呢?答案是必然的,所以我们应该采取什么办法去防范呢?

进程组

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

如上面的pgid就是进程组id

组⻓进程
“组长进程” 指的是 进程组的组长,也就是 PGID(进程组 ID)等于该进程 PID 的那个进程。

进程组组⻓的作⽤: 进程组组⻓可以创建⼀个进程组或者创建该组中的进程

进程组的⽣命周期: 从进程组创建开始到其中最后⼀个进程离开为⽌。注意: 主要某个进程组中有⼀个进程存在, 则该进程组就存在, 这与其组⻓进程是否已经终⽌⽆关

会话:在 Linux 中,“会话(Session)” 是比进程组(Process Group)更高一级的进程组织单位,每个会话可以包含多个进程组,但只能有一个前台进程组。

如何创建会话呢?

include /

功能:创建会话*返回值:创建成功返回SID, 失败返回-1

pid_t setsid(void);

接下来我们就自己实现一个守护进程

#pragma once
#include
#include
#include
#include
#include
#include
#include
#include"Log.hpp"
using namespace LogMoudle;
//将服务进行守护进程化的服务
const std::string dev="/dev/null";
void Daemon(){
    //忽略信号
    signal(SIGPIPE,SIG_IGN);
    signal(SIGCHLD,SIG_IGN);
    if(fork()>0)
        //父进程退出
        exit(0);
    //子进程继续,孤儿进程,父进程就是1
    setsid();
    //守护进程不要重键盘输入也不需要向显示器打印
    //方法一:关闭0,1,2(不推荐)
    //方法二:打开/dev/null将标准0,1,2重定向到/dev/null
    int fd=open(dev.c_str(),O_RDWR);
    if(fd<0){
        LOG(LogLevel::FATAL)<<"打开"<

linux中也有自己的系统调用:

daemon:

参数含义
nochdir传 0 → 将工作目录切到 /;非 0 → 保持原目录
noclose传 0 → 把 stdin/stdout/stderr 重定向到 /dev/null;非 0 → 保持原打开文件

这就是守护进程,它本质是一个子进程。

与孤儿进程对比

维度守护进程(daemon)孤儿进程(orphan process)
产生方式有意设计:进程主动调用 daemon() 或手动 fork+setsid+双fork 等步骤,使自己脱离终端、会话和父进程。无意产生:父进程先 exit,子进程仍在运行,于是被 init(或 systemd)“收养”,瞬间变成孤儿。
是否预期开发者 主动想要 的后台服务。意外事件,程序员通常不希望出现。
父进程最终 PPID = 1(被 init 收养)。同样 PPID = 1(被 init 收养)。
控制终端无 TTY(自己调用 setsid() 创建新会话并脱离终端)。可能仍有原 TTY,直到该终端关闭;不保证脱离。
会话/进程组自己新建 会话(SID=PID) 和 进程组(PGID=PID),成为会话首进程+组长。沿用原来的 会话和进程组,不会自动调用 setsid(),因此不是会话首进程。
生命周期系统级服务,常驻,随系统关闭或手动 systemctl stop 结束。随自身逻辑结束;生命周期与“孤儿”状态无关,只是父进程换了。
资源占用主动 chdir("/")umask(0)、关闭/重定向 0/1/2,资源干净。保持原工作目录、文件描述符、信号处理等,可能残留资源。
日志/输出自己接管 syslog 或文件,不往终端写。若原来 stdout 指向终端,可能继续写,但终端已关闭时会收到 SIGPIPE 或写失败。
示例httpdsshdcrondsystemd-logind 等系统服务。bash 里执行 sleep 100 & 后退出 bash;sleep 瞬间成为孤儿进程。
一句话总结“主动离婚,净身出户,另立门户” —— 脱离终端、脱离父进程,成为后台服务。“父母双亡,被 init 收养” —— 只是父进程先死,子进程被动变成孤儿,没有做脱离操作。

今天的更新就到这里,如有错误欢迎指出!!!