深入了解 Linux 系统中的前置任务、后台任务和守护进程
⭐小白苦学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来终止该守护进程。
推荐阅读
-
深入了解 Linux 系统中的前置任务、后台任务和守护进程
-
windows下进程间通信的(13种方法)-摘 要 本文讨论了进程间通信与应用程序间通信的含义及相应的实现技术,并对这些技术的原理、特性等进行了深入的分析和比较。 ---- 关键词 信号 管道 消息队列 共享存储段 信号灯 远程过程调用 Socket套接字 MQSeries 1 引言 ---- 进程间通信的主要目的是实现同一计算机系统内部的相互协作的进程之间的数据共享与信息交换,由于这些进程处于同一软件和硬件环境下,利用操作系统提供的的编程接口,用户可以方便地在程序中实现这种通信;应用程序间通信的主要目的是实现不同计算机系统中的相互协作的应用程序之间的数据共享与信息交换,由于应用程序分别运行在不同计算机系统中,它们之间要通过网络之间的协议才能实现数据共享与信息交换。进程间通信和应用程序间通信及相应的实现技术有许多相同之处,也各有自己的特色。即使是同一类型的通信也有多种的实现方法,以适应不同情况的需要。 ---- 为了充分认识和掌握这两种通信及相应的实现技术,本文将就以下几个方面对这两种通信进行深入的讨论:问题的由来、解决问题的策略和方法、每种方法的工作原理和实现、每种实现方法的特点和适用的范围等。 2 进程间的通信及其实现技术 ---- 用户提交给计算机的任务最终都是通过一个个的进程来完成的。在一组并发进程中的任何两个进程之间,如果都不存在公共变量,则称该组进程为不相交的。在不相交的进程组中,每个进程都独立于其它进程,它的运行环境与顺序程序一样,而且它的运行环境也不为别的进程所改变。运行的结果是确定的,不会发生与时间相关的错误。 ---- 但是,在实际中,并发进程的各个进程之间并不是完全互相独立的,它们之间往往存在着相互制约的关系。进程之间的相互制约关系表现为两种方式: ---- (1) 间接相互制约:共享CPU ---- (2) 直接相互制约:竞争和协作 ---- 竞争——进程对共享资源的竞争。为保证进程互斥地访问共享资源,各进程必须互斥地进入各自的临界段。 ---- 协作——进程之间交换数据。为完成一个共同任务而同时运行的一组进程称为同组进程,它们之间必须交换数据,以达到协作完成任务的目的,交换数据可以通知对方可以做某事或者委托对方做某事。 ---- 共享CPU问题由操作系统的进程调度来实现,进程间的竞争和协作由进程间的通信来完成。进程间的通信一般由操作系统提供编程接口,由程序员在程序中实现。UNIX在这个方面可以说最具特色,它提供了一整套进程间的数据共享与信息交换的处理方法——进程通信机制(IPC)。因此,我们就以UNIX为例来分析进程间通信的各种实现技术。 ---- 在UNIX中,文件(File)、信号(Signal)、无名管道(Unnamed Pipes)、有名管道(FIFOs)是传统IPC功能;新的IPC功能包括消息队列(Message queues)、共享存储段(Shared memory segment)和信号灯(Semapores)。 ---- (1) 信号 ---- 信号机制是UNIX为进程中断处理而设置的。它只是一组预定义的值,因此不能用于信息交换,仅用于进程中断控制。例如在发生浮点错、非法内存访问、执行无效指令、某些按键(如ctrl-c、del等)等都会产生一个信号,操作系统就会调用有关的系统调用或用户定义的处理过程来处理。 ---- 信号处理的系统调用是signal,调用形式是: ---- signal(signalno,action) ---- 其中,signalno是规定信号编号的值,action指明当特定的信号发生时所执行的动作。 ---- (2) 无名管道和有名管道 ---- 无名管道实际上是内存中的一个临时存储区,它由系统安全控制,并且独立于创建它的进程的内存区。管道对数据采用先进先出方式管理,并严格按顺序操作,例如不能对管道进行搜索,管道中的信息只能读一次。 ---- 无名管道只能用于两个相互协作的进程之间的通信,并且访问无名管道的进程必须有共同的祖先。 ---- 系统提供了许多标准管道库函数,如: pipe——打开一个可以读写的管道; close——关闭相应的管道; read——从管道中读取字符; write——向管道中写入字符; ---- 有名管道的操作和无名管道类似,不同的地方在于使用有名管道的进程不需要具有共同的祖先,其它进程,只要知道该管道的名字,就可以访问它。管道非常适合进程之间快速交换信息。 ---- (3) 消息队列(MQ) ---- 消息队列是内存中独立于生成它的进程的一段存储区,一旦创建消息队列,任何进程,只要具有正确的的访问权限,都可以访问消息队列,消息队列非常适合于在进程间交换短信息。 ---- 消息队列的每条消息由类型编号来分类,这样接收进程可以选择读取特定的消息类型——这一点与管道不同。消息队列在创建后将一直存在,直到使用msgctl系统调用或iqcrm -q命令删除它为止。 ---- 系统提供了许多有关创建、使用和管理消息队列的系统调用,如: ---- int msgget(key,flag)——创建一个具有flag权限的MQ及其相应的结构,并返回一个唯一的正整数msqid(MQ的标识符); ---- int msgsnd(msqid,msgp,msgsz,msgtyp,flag)——向队列中发送信息; ---- int msgrcv(msqid,cmd,buf)——从队列中接收信息; ---- int msgctl(msqid,cmd,buf)——对MQ的控制操作; ---- (4) 共享存储段(SM) ---- 共享存储段是主存的一部分,它由一个或多个独立的进程共享。各进程的数据段与共享存储段相关联,对每个进程来说,共享存储段有不同的虚拟地址。系统提供的有关SM的系统调用有: ---- int shmget(key,size,flag)——创建大小为size的SM段,其相应的数据结构名为key,并返回共享内存区的标识符shmid; ---- char shmat(shmid,address,flag)——将当前进程数据段的地址赋给shmget所返回的名为shmid的SM段; ---- int shmdr(address)——从进程地址空间删除SM段; ---- int shmctl (shmid,cmd,buf)——对SM的控制操作; ---- SM的大小只受主存限制,SM段的访问及进程间的信息交换可以通过同步读写来完成。同步通常由信号灯来实现。SM非常适合进程之间大量数据的共享。 ---- (5) 信号灯 ---- 在UNIX中,信号灯是一组进程共享的数据结构,当几个进程竞争同一资源时(文件、共享内存或消息队列等),它们的操作便由信号灯来同步,以防止互相干扰。 ---- 信号灯保证了某一时刻只有一个进程访问某一临界资源,所有请求该资源的其它进程都将被挂起,一旦该资源得到释放,系统才允许其它进程访问该资源。信号灯通常配对使用,以便实现资源的加锁和解锁。 ---- 进程间通信的实现技术的特点是:操作系统提供实现机制和编程接口,由用户在程序中实现,保证进程间可以进行快速的信息交换和大量数据的共享。但是,上述方式主要适合在同一台计算机系统内部的进程之间的通信。 3 应用程序间的通信及其实现技术 ---- 同进程之间的相互制约一样,不同的应用程序之间也存在竞争和协作的关系。UNIX操作系统也提供一些可用于应用程序之间实现数据共享与信息交换的编程接口,程序员可以通过自己编程来实现。如远程过程调用和基于TCP/IP协议的套接字(Socket)编程。但是,相对普通程序员来说,它们涉及的技术比较深,编程也比较复杂,实现起来困难较大。 ---- 于是,一种新的技术应运而生——通过将有关通信的细节完全掩盖在某个独立软件内部,即底层的通讯工作和相应的维护管理工作由该软件内部来实现,用户只需要将通信任务提交给该软件去完成,而不必理会它的具体工作过程——这就是所谓的中间件技术。 ---- 我们在这里分别讨论这三种常用的应用程序间通信的实现技术——远程过程调用、会话编程技术和MQSeries消息队列技术。其中远程过程调用和会话编程属于比较低级的方式,程序员参与的程度较深,而MQSeries消息队列则属于比较高级的方式,即中间件方式,程序员参与的程度较浅。 ---- 4.1 远程过程调用(RPC)