深入理解Linux系统中的前后台任务与守护进程

发布于:2024-04-17 ⋅ 阅读:(25) ⋅ 点赞:(0)

小白苦学IT的博客主页

初学者必看:Linux操作系统入门

代码仓库:Linux代码仓库

❤关注我一起讨论和学习Linux系统

1.前言

在Linux系统中,进程管理是至关重要的一个环节。其中,前后台任务和守护进程是进程管理中不可忽视的两个概念。前后台任务决定了进程与用户交互的方式,而守护进程则以其独特的运行方式,为系统提供稳定且持续的服务。本文将深入探讨Linux系统中的前后台任务与守护进程,帮助读者更好地理解和运用它们。

2.前后台任务的理解与体现

在Linux系统中,进程(process)是程序执行的实例,而任务(task)通常是指进程所要执行的具体工作。当我们谈到前后台任务时,我们实际上是在讨论进程与用户交互的方式以及它们在终端中的表现。

2.1前台任务

前台任务是指那些直接与终端交互的进程。当我们在终端中输入命令并按下回车键时,这个命令通常会作为一个前台任务启动。前台任务占据整个终端窗口,它的输出会直接显示在终端上,而任何需要用户输入的操作也会直接在终端上提示。前台任务通常需要用户的实时关注,因为它依赖于用户的输入来继续执行。

前台任务的一个显著特点是它会阻塞终端,这意味着当前台任务正在运行时,用户不能在同一终端窗口中启动其他任务。如果前台任务是一个长时间运行的操作,比如文件复制或大型程序的编译,用户可能需要等待它完成才能继续在终端中工作。

2.2后台任务

与前台任务不同,后台任务是在后台运行的进程,它们不与终端直接交互。后台任务通常通过在前台任务运行时按下Ctrl + Z暂停,然后使用bg命令将其放到后台继续执行。后台任务会释放终端的控制权,使得用户可以在同一终端窗口中启动其他任务。

后台任务的输出通常不会直接显示在终端上,而是可能被重定向到文件或其他地方。用户可以通过其他方式(如查看日志文件或使用特定命令)来检查后台任务的执行状态和结果。后台任务不依赖于用户的实时输入,它们可以在用户离开终端或执行其他任务时继续运行。

2.3前后台任务的切换与管理

下面我们用这样一段代码来进行测验:

我们将其运行起来之后,通过输入命令发现命令行没有反应:

以下我暂时把任务用进程的说法来说:原因在于,process这个进程运行之后成了前台进程,而bash进程(也就是我们输入命令的进程)自动被被=切换到了后台进程,而后台进程不能与用户交互,所以用户输入的命令会没有反应。如果我们要将process这个进程切换到后台,可以先ctrl+z,然后用bg命令将其切换到后台进程,此时bash进程会被自动切换到前台进程,因为前台只有一个进程并且必须都要有一个进程与用户进行交互,所以当前台进程(非bash进程)被切换时,那么处于后台的bash会直接被系统自动切换到前台。

下面我们把process这个进程输出的内容重定向到一个log.txt的文件中作为一个后台进程

上图中./process >> log.txt &  是将该进程输出的内容重定向到log.txt中以后台进程的方式执行任务,通过jobs可以查看后台进程的任务号,状态信息,fg 任务号是把指定任务号的后台进程切换到前台进程中执行,ctrl + z是把前台进程停下来,然后切换到后台进程,bash会自动切换到前台进程。

总结一下就是:

1.将前台任务转为后台任务

  • 使用Ctrl + Z组合键可以将正在运行的前台任务暂停并放到后台。此时任务处于暂停状态。
  • 使用bg命令可以将一个在后台暂停的命令变成在后台继续执行。

2.直接在后台启动任务

  • 在命令的后面添加&字符,可以在后台启动一个任务。这样即使关闭当前的终端,任务也会继续在后台运行。

3.查看后台任务

  • 使用jobs命令可以查看当前终端后台运行的任务。
  • 使用ps命令也可以查看后台运行的任务,但它显示的是系统中所有进程的状态,不仅仅是后台任务。

4.关闭后台任务

  • 要关闭后台任务,首先需要找到该任务的进程ID(PID),然后使用kill命令加上PID来终止任务。

如何理解前台任务只能有一个,而后台任务可以有多个  ?

在Linux系统中,前台任务只能有一个,而后台任务可以有多个,这主要基于终端交互和任务管理的需求。

首先,前台任务是与用户直接交互的任务,它独占命令行窗口。在大多数情况下,用户希望与一个任务进行实时的、专注的交互,而不是同时与多个任务交互,这可能导致混乱和效率下降。因此,系统限制一次只能有一个前台任务,确保用户可以与当前任务进行清晰、集中的交互。

其次,后台任务的设计是为了在用户不需要直接交互的情况下执行任务。后台任务可以在不干扰前台任务的情况下运行,并允许用户同时执行其他命令或任务。因此,多个后台任务可以同时运行,为用户提供更大的灵活性和多任务处理能力。

此外,从系统资源管理的角度来看,后台任务虽然运行在后台,但仍然占用系统资源。如果有过多的前台任务同时运行,可能会导致系统资源紧张,影响系统的稳定性和性能。而后台任务由于其非交互性质,可以更有效地共享和分配系统资源,避免资源冲突和浪费。   

Linux作为一个多用户、多任务的操作系统,允许多个用户同时登录并进行操作。

2.4进程组和任务的关系

任务其实是由进程组去完成,一个进程可以自成一组,任务会指派给进程组,多个任务在同一个session内启动的sid是一样的。

我们发现sid是29832,而我们通过查看该sid发现:

其实就是bash的id,所以这个session是被bash创建的,并以bash的pid作为sid.

3.理解session窗口

Session窗口在计算机领域中,特别是在Linux操作系统和某些应用框架(如Apache Flink)中,是指用户登录后拥有的一系列进程、窗口站、桌面和窗口的集合。这个集合代表了一个用户的工作站登录会话,是用户与系统进行交互的界面和平台。

故事时刻:

下面,我将通过一个简单的故事来解释Session窗口的概念:

在一个繁忙的图书馆里,每个读者都有一个专属的座位和书桌,这个座位和书桌就可以类比为一个Session窗口。当读者(用户)坐下来开始阅读或学习时,他们就进入了一个会话(Session)。在这个会话中,读者可以打开多本书(相当于打开多个应用程序或窗口),进行各种学习和研究活动。

假设一个读者(我们称他为小明)想要写一篇关于历史的论文。他坐下后,打开了他的电脑(登录系统,开始一个Session),并在桌面上打开了多个窗口:一个窗口用于浏览网页查找资料,另一个窗口用于编写论文,还有一个窗口用于与导师或同学交流讨论。这些窗口就构成了小明在这个Session中的工作环境。

在这个故事中,小明的座位和书桌(Session窗口)是他进行学习和工作的平台,而他在平台上打开的各种书籍和窗口则是他完成任务所需的工具和资源。就像在计算机中,用户通过Session窗口与系统交互,执行各种任务,打开和关闭应用程序,管理文件和资源。

值得注意的是,每个读者(用户)在图书馆都有自己的座位和书桌(Session窗口),互不干扰。同样,在计算机系统中,每个用户也有自己的Session窗口,保证了各自工作的独立性和安全性。

通过这个故事,我们可以更好地理解Session窗口的概念和作用:它为用户提供了一个独立、私有的工作环境,使用户能够高效、安全地执行各种任务。

每个用户通过一次登录会形成一个session,而我们知道Linux是一个多用户多进程的操作系统,所以必然可以多个用户同时登录,形成多个session窗口,该如何理解呢?

Linux操作系统可以有多个session窗口,这主要基于其多任务处理的特性和用户交互的需求。

首先,Linux作为一个多用户、多任务的操作系统,允许多个用户同时登录并进行操作。每个用户登录后,系统都会为其创建一个独立的session,这样每个用户都有自己独立的操作环境,互不干扰。每个session都包含了用户登录、执行命令、注销等一系列操作,具有持续性和独立性。

其次,即使对于单个用户,也可能需要同时管理多个任务或项目。在这种情况下,用户可以通过创建多个session窗口来分别处理这些任务。每个session窗口都可以看作是一个独立的终端环境,用户可以在不同的窗口中执行不同的命令或运行不同的程序。

此外,Linux中的session不仅仅局限于本地终端窗口,还可以通过远程连接(如SSH)创建远程session。这样,用户即使不在本地计算机前,也能通过远程session访问和管理Linux系统。

因此,Linux操作系统可以有多个session窗口,这为用户提供了极大的灵活性和便利性,使其能够同时处理多个任务或项目,提高工作效率。同时,多个session窗口的存在也保证了不同用户或任务之间的独立性,避免了相互干扰。

4.守护进程

4.1初识守护进程

我们日常玩的游戏当中,就拿王者荣耀来说吧,王者荣耀我们知道为什么会有人可以三更半夜还能玩这个游戏呢?其实是服务器24小时持续为我们提供服务的,而服务器24小时持续为我们提供服务的背后,与守护进程(Daemon)的运行机制有着密切的关系。守护进程是在计算机操作系统中以后台方式运行的长期进程,它负责执行一些特定的任务或提供某种服务。

守护进程的设计理念是为了在系统启动后,持续提供服务或执行任务,而不需要交互式用户干预。它们通常在系统启动时自动启动,并持续运行直到系统关闭或显式停止。这种长期运行的特性使得守护进程非常适合用于需要在后台持续运行的服务,如网络监听、文件同步、定时任务等。

服务器上的许多服务都是通过守护进程来实现的。例如,Web服务器软件(如Apache或Nginx)通常以守护进程的形式运行,监听网络请求并提供网页内容。数据库服务器(如MySQL或PostgreSQL)也会以守护进程的方式运行,处理数据库查询和存储数据。这些守护进程确保服务器能够持续、稳定地提供服务,满足用户的各种需求。

此外,守护进程还具有无人值守的特点,它们可以独立运行并完成其任务,无需用户的实时干预。这使得服务器能够在无人值守的情况下稳定运行,提供持续的服务。即使系统管理员不在现场,服务器也能通过守护进程继续提供服务,确保业务的连续性。

4.2守护进程与普通进程的区别

1.运行环境

  • 守护进程独立于用户的登录会话,可以在系统启动时自动运行,并持续在后台运行。
  • 普通进程则依赖于用户的操作或终端会话来启动和运行。

2.权限与特权

  • 守护进程通常以超级用户权限(root)运行,这意味着它们可以访问系统的各种资源和敏感信息。
  • 普通进程的权限通常受到用户的限制,无法执行一些需要特权的操作。

3.生命周期

  • 守护进程通常是长期驻留于内存中的,它们会在系统启动时被启动,并持续运行,直到系统关闭或管理员手动停止。
  • 普通进程的生命周期则通常与用户的操作或终端会话相关,当用户退出登录或关闭终端时,普通进程也会随之终止。

4.交互性

  • 守护进程是在后台运行的,它们通常没有控制台窗口,也不需要交互式的用户界面。它们的主要任务是执行后台任务或提供服务。
  • 普通进程则通常与用户进行交互,可能需要用户输入或向用户展示输出

5.任务与功能

  • 守护进程主要用于提供系统级的服务,如网络服务(如Web服务器、数据库服务器)、日志记录、定时任务调度等。
  • 普通进程则执行各种任务,其范围广泛,从简单的命令行工具到复杂的图形界面应用程序等。

6.独立性

  • 守护进程在系统级别运行,与特定用户无关,它们不会受到特定用户登录或注销的影响。
  • 普通进程则可能受到用户会话状态的影响。

4.3守护进程如何不受用户登录登出影响的?

守护进程是通过自行形成一个session窗口来实现不受用户登录登出影响的目标。在Linux系统中,守护进程是一种特殊的进程,它会在系统启动时开始运行,并在后台持续提供服务或执行任务。为了实现这一目标,守护进程需要脱离与用户终端的关联,确保用户的登录登出操作不会影响其运行。

具体来说,守护进程创建过程中会涉及一些关键步骤。首先,它会fork一个子进程并让父进程退出,这样子进程就会成为孤儿进程,被init进程接管。然后,子进程会调用setsid()函数创建一个新的会话,并成为该会话的领头进程。这个新的会话不再与原来的终端相关联,因此守护进程就脱离了终端的控制。

此外,守护进程还会更改当前工作目录到根目录,重设文件权限掩码,并关闭所有不必要的文件描述符,以确保其运行环境的独立性。这些步骤共同确保了守护进程能够在后台稳定运行,不受用户登录登出操作的影响。

因此,可以说守护进程是通过自行形成一个独立的session窗口来实现其特殊功能的。这个独立的session窗口使得守护进程能够与用户终端解耦,从而实现长时间、稳定地提供服务或执行任务的目标。

4.4编写守护进程代码

#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const std::string nullfile = "/dev/null";

void Daemon(const std::string & cwd="")
{
    //1.忽略其他异常信号
    signal(SIGCLD,SIG_IGN);
    signal(SIGPIPE,SIG_IGN);
    signal(SIGSTOP,SIG_IGN);

    //2.将自己变成独立的会话
    if(fork()>0)
    {
        exit(0);
    }
    setsid();

    //3.更改当前调用进程的工作目录
    if(!cwd.empty())
        chdir(cwd.c_str());
    
    //4.标准输入,标准输出,标准错误重定向到/dev/null
    int fd = open(nullfile.c_str(),O_RDWR);
    if(fd > 0)
    {
        dup2(fd,0);
        dup2(fd,1);
        dup2(fd,2);
        close(fd);
    }
}

只需要在启动服务之前,调用该函数就可以使进程变成守护进程自动形成要给会话在后台运行,如果想终止守护进程,那么只需要通过kill -9 进程pid来终止该守护进程。