终端关闭时如何让进程不退出

1.终端与 bash 进程

查看 bash 进程的命令如下:

ps -ef | grep bash

在这里插入图片描述

每连接一个虚拟终端到 Ubuntu 操作系统,就会出现一个 bash 进程。

bash (Bourne Again Shell) 是 shell 的一种,bash 是多数 Linux 系统默认的 shell。bash 是一个可执行程序,主要作用就是把用户输入的命令翻译给操作系统(命令解释器)。

2.终端上的开启进程

创建一个 test.c 文件,其内容如下:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char* const* argv)
{
    printf("你好,世界!\n");
    for (;;)
    {
        sleep(1);
        printf("休息1秒\n");
    }
    printf("程序退出,再见!\n");
    return 0;
}

编译 test.c 文件的命令如下:

gcc -o test test.c

运行可执行文件 test 的命令如下:

./test

在这里插入图片描述

从上图可以看出,test 进程是 bash 进程的子进程。

对于那些由用户执行命令所启动的进程都是与终端相关的,当把终端关闭,该终端中的所有进程也都会自动关闭。

在 Linux 中,进程之间的关系如下:

在这里插入图片描述

3.进程组与会话

在 Linux 中,每一个进程还属于一个进程组,一个进程组由一个或者多个进程组成。通常,它们联合起来作业,可以接受同一个终端下的各种信号。并且每一个进程组都有一个唯一的进程组ID(在 Linux 中叫做 PGID),进程组中有一个组长进程,组长进程的标识是它的进程ID和组ID相同。一般,一个进程组中第一个创建的进程就是组长进程。一个进程组中只要还有一个进程存在,那么这个进程组就存在。我们可以调用系统函数来创建进程组、加入进程组。

会话(session)是一个或者多个进程组的集合,一般情况下,只要不进行特殊的系统函数调用,一个 bash 上边运行的所有程序都属于一个会话。会话有一个 session leader,通常这个 bash 就是 session leader。

在这里插入图片描述

指定输出字段与格式以显示进程属性的命令如下:

ps -eo pid,ppid,pgid,sid,tty,comm | grep -E 'bash|PID|test'

关于 ps 命令各个选项和参数的含义:https://wker.com/linux-command/ps.html

在这里插入图片描述

如果我们要把终端断开的话,系统就会发送 SIGHUP 信号(即终端断开信号)给 session leader(即这个 bash 进程),bash 进程收到 SIGHUP 信号后,bash 就会把这个 SIGHUP 信号发送给 session 里边的所有进程,收到这个 SIGHUP 信号的进程的缺省动作就是退出。

4.strace 工具的使用

strace 工具是 Linux 下调试分析诊断工具,可以跟踪程序执行时进程的系统调用以及所收到的信号。

跟踪 test 进程的命令如下:

sudo strace -e trace=signal -p 1238

跟踪 bash 进程的命令如下:

sudo strace -e trace=signal -p 1164

我们直接关闭 test 程序所在的终端,上述两条命令的输出结果如下:

在这里插入图片描述

在这里插入图片描述

5.终端关闭时如何让进程不退出

5.1 test 进程拦截 SIGHUP 信号

5.1.1 SIG_IGN 标志

test 进程收到 SIGHUP 信号之后,告诉操作系统“请不要把我杀死”。

修改 test.c 的内容如下:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

int main(int argc, char* const* argv)
{
    printf("你好,世界!\n");

    // SIG_IGN标志:要求忽略这个信号,请求操作系统不要用缺省的处理方式来对待我,即不要把我杀掉
    signal(SIGHUP, SIG_IGN);
    
    for (;;)
    {
        sleep(1);
        printf("休息1秒\n");
    }
    printf("程序退出,再见!\n");

    return 0;
}

编译 test.c

gcc -o test test.c

运行 test

./test

查看进程:

ps -eo pid,ppid,pgid,sid,tty,comm | grep -E 'bash|PID|test'

在这里插入图片描述

我们直接关闭 test 程序所在的终端,从下图可以看到,bash 进程被杀死了,test 进程仍然存在:

在这里插入图片描述

5.1.2 nohup 命令

使用 nohup 命令启动的进程能够忽略掉 SIGHUP 信号,该命令会把屏幕输出重新定位到当前目录的 nohup.out 文件中。

test.c 的内容如下:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char* const* argv)
{
    printf("你好,世界!\n");
    for (;;)
    {
        sleep(1);
        printf("休息1秒\n");
    }
    printf("程序退出,再见!\n");
    return 0;
}

编译 test.c

gcc -o test test.c

运行 test

nohup ./test

查看进程:

ps -eo pid,ppid,pgid,sid,tty,comm | grep -E 'bash|PID|test'

在这里插入图片描述

我们直接关闭 test 程序所在的终端,查看进程:

在这里插入图片描述

5.2 让 test 进程和 bash 进程不在同一个 session 里

5.2.1 setsid() 函数

需要注意的是,进程组组长调用 setsid() 函数是无效的。

修改 test.c 的内容如下:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char* const* argv)
{
    pid_t pid;

    printf("你好,世界!\n");

    pid = fork(); // 系统函数,用来创建新进程。子进程会从fork()调用之后开始执行。
    
    if (pid < 0)
    {
        printf("fork()进程出错!\n");
    }
    else if (pid == 0)
    {
        printf("子进程开始执行!\n");
        setsid(); // 新建立一个不同的session
        for (;;)
        {
            sleep(1);
            printf("子进程休息1秒\n");
        }
        return 0;
    }
    else
    {
        printf("父进程开始执行!\n");
        for (;;)
        {
            sleep(1);
            printf("父进程休息1秒\n");
        }
        return 0;
    }

    printf("程序退出,再见!\n");
    
    return 0;
}

编译 test.c

gcc -o test test.c

运行 test

./test

查看进程:

ps -eo pid,ppid,pgid,sid,tty,comm | grep -E 'bash|PID|test'

在这里插入图片描述

我们直接关闭 test 程序所在的终端,查看进程:

在这里插入图片描述

5.2.2 setsid 命令

使用 setsid 命令启动一个进程能够使启动的进程在一个新的 session 中,这样的话,终端关闭时该进程就不会退出。

test.c 的内容如下:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char* const* argv)
{
    printf("你好,世界!\n");
    for (;;)
    {
        sleep(1);
        printf("休息1秒\n");
    }
    printf("程序退出,再见!\n");
    return 0;
}

编译 test.c

gcc -o test test.c

运行 test

setsid ./test

查看进程:

ps -eo pid,ppid,pgid,sid,tty,comm | grep -E 'bash|PID|test'

在这里插入图片描述

我们直接关闭 test 程序所在的终端,查看进程:

在这里插入图片描述

6.后台运行

后台运行的命令如下:

./test &

在这里插入图片描述

后台执行这个程序的同时,终端能够干其他事情;如果不用后台执行,那么终端就只能等这个程序完成后才能继续执行其他的操作。

切换到前台的命令如下:

fg

在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值