进程间关系和守护进程---理论+手撕代码(详细版)

目录

进程组:

组长进程:

进程组的生命周期:

会话(session):

作业控制:

守护进程:

进程组:

多个进程可以组合成为一个进程组,Linux为了管理这些进程组,会给每个进程组分配一个唯一的进程组ID,即PGID,是一个正整数,类型为pid_t;

先来写个demo代码,看一下进程的PGID:

#include <iostream>
#include <unistd.h>
#include <cstdio>
int main()
{
    pid_t pid = fork();
    if (pid == 0)
    {
        while (true)
        {
            printf("i am child process!,pid = %d\n", getpid());
            sleep(1);
        }
    }
    printf("i am Main Process!,pid = %d\n",getpid());
    sleep(100);
    return 0;
}

#Makefile
Process:Process.cc
	g++ -o $@ $^ -std=c++14
.PHONY:clean
clean:
	rm -f Process

 make一下,使用命令:

ps -axj | head -1 && ps -axj | grep Process

现象:可以发现在这个例子中,Process父子进程属于同一个进程组,PGID一样且为Process父进程的pid

组长进程:

每一个进程组都有一个组长进程。 组长进程的 ID 等于其进程 ID 。我们可以通过 ps 命令观察现象:
ps -o pid,pgid,ppid,comm | cat

现象:

可以发现ps指令和cat同属一个进程组,组长进程为bash

进程组的生命周期:

 从进程组创建开始到其中最后一个进程离开为止。注意: 主要某个进程组中有一个进程存在, 则该进程组就存在, 这与其组长进程是否已经终 止无关。

会话(session):

多个进程组可以组成一个会话,同样的,Linux为了管理会话,会为每一个会话分配一个唯一的SID

先看现象:

ps -o pid,pgid,ppid,sid,comm | cat 

现象:

在这了例子中会话id就是bash进程的pid;
同一个会话中,可以同时运行多个进程组,但是在同一时刻只能允许一个前台进程(组),多个后台进程(组);

作业控制:

作业 是针对用户来讲,用户完成某项任务而启动的进程,一个作业既可以只包含
一个进程,也可以包含多个进程,进程之间互相协作完成任务, 通常是一个进程
管道。
Shell 分前后台来控制的不是进程而是作业 或者进程组。一个前台作业可以由多
个进程组成,一个后台作业也可以由多个进程组成, Shell 可以同时运⾏一个前台
作业和任意多个后台作业,这称为 作业控制
查询作业状态的命令:jobs
先来个demo代码:
#include <iostream>
#include <unistd.h>
#include <cstdio>
int main()
{
    while(true)
    {

    }
    return 0;
}

make编译后,&后台运行,,再使用jobs查询

表示Process已经在后台处于运行状态;

此时Process进程是无法接受从标准输入得到的任何信息的,ctrl + c也无法终止

将后台的作业挂到前台指令:fd+作业号

使用ctrl + z 挂起前台进程,以Process为例:

再次启动Process进程命令:bg + 作业号:

守护进程:

创建会话api:

return val:成功返回sid,失败返回-1

要想让这个函数执行成功,首先要保证调用这个函数的进程不是所属进程组的组长!即可以先fork子进程,先让父进程退出,子进程成为孤儿进程(守护进程);

Daemon函数设计:

#pragma once
#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static const std::string default_path = "/";
static const std::string outputfile = "/dev/null";
void Daemon(bool chdircwd, bool iscloesfd)
{
    // 先忽略信号
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);

    pid_t pid = fork();

    (void)setsid();

    if (pid > 0)
        exit(0);

    if (chdircwd)
    {
        ::chdir(default_path.c_str());
    }

    if (iscloesfd)
    {
        ::close(0);
        ::close(1);
        ::close(3);
    }
    else
    {
        int fd = ::open(outputfile.c_str(),O_RDWR);
        if(fd > 0)
        {
            ::dup2(fd,0);
            ::dup2(fd,1);
            ::dup2(fd,2);
            ::close(fd);
        }
    }
}

外部测试:

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


int main()
{
    Daemon(false,false);
    while(true)
    {}
    return 0;
}



#makefile
Process:Process.cc
	g++ -o $@ $^ -std=c++14
.PHONY:clean
clean:
	rm -f Process

make一下,发现并没有阻塞住,使用命令查一下Process进程

ps -axj | head -1 && ps -ajx | grep Process

现象:

done

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值