任务管理与守护进程

简介: 任务管理与守护进程

一、任务管理

1.1 进程组概念

进程组是一个或多个进程的集合,每个进程都属于一个进程组,引入进程组的目的是为了简化对进程的管理。每个进程组都可以有一个组长进程(由进程组第一个创建的进程担任),组长进程ID等于其进程组ID。组长进程可以创建一个进程组,创建该组中的进程,然后终止

通常,进程组与同一作业相关联,可以接收来自同一终端的各种信号

注意:只要在某个进程组中有一个进程存在,则该进程组就存在,与其组长进程是否终止无关

1.2 会话概念

会话(Session)是一个或多个进程组的集合


一个会话可以有一个控制终端,这通常是登录到其上的终端设备(在终端登录情况下)或伪终端设备(在网络登录情况下)。建立与控制终端连接的会话首进程被称为控制进程。一个会话中的几个进程组可被分为一个前台进程组以及一个或多个后台进程组。所以


所以一个会话中,应该包括控制进程(会话首进程),一个前台进程组和任意多个后台进程组

下面使用sleep命令生成了五个进程(两个后台进程&&三个前台进程)

其中sleep 10000与sleep 20000属于同一个后台进程组,sleep 30000、sleep 40000和sleep 50000属于同一个前台进程组

这些进程组的控制终端相同,同属于一个会话,当用户在控制终端输入特殊的控制键(如Ctrl+C产生SIGINT,Ctrl+\产生SIGQUIT,Ctrl+Z产生SIGTSTP),内核就会发送相应的信号给前台进程组中的所有进程

b444cb9c595c4c2c8751cb5389f6c654.png

1.3 作业概念

Shell分前后台来控制的不是进程而是作业(Job)或者进程组(Process Group)。


一个前台作业可以由多个进程组成,一个后台作业也可以由多个进程组成,Shell可以运行一个前台作业和任意多个后台作业,这被称为作业控制


作业与进程组的区别:


若作业中的某个前台进程创建了子进程,子进程并不属于该作业。一旦作业运行结束,Shell就将自己提到前台,若原来的前台进程创建的子进程还没有终止,该子进程将自动变为后台进程组


1.4 相关操作

1.4.1 前台进程&后台进程

直接运行某一可执行程序,如./可执行程序,默认将进程放到前台运行,其状态后有+号,如R+


002bfffd54c94ff2a72518da7032fe94.png


运行可执行程序时在后面加上&,可指定将程序放到后台运行,如./可执行程序,其状态后无+号


af3f0d7a54104de589fe664ae5c271f5.png


将程序放到后台运行时会发现多了一行提示信息,如上图的 [1] 17824


其中[1]是作业的编号,若同时运行多个作业可以用这个编号进行区分,17824是该后台进程的PID


1.4.2 jobs、fg、bg

使用jobs命令,可以查看当前会话中有哪些作业

4f579aba0be84e0d90b5ca34f7b6af35.png



使用fg命令,可以将某个作业提至前台运行,若该作业正在后台运行则直接提至前台运行,若该作业处于停止状态,则给进程组的每个进程发SIGCONT信号使其继续运行并提至前台


9c6122006e354b92ad14672b2dd17ad1.png


由于1号作业被提至前台运行,所以其运行状态也由R变成了R+


注意:前台进程只能有一个,当某个进程变成前台进程后,bash会自动变为后台进程,此时bash无法进行命令行解释


使用Ctrl+Z可以将进程放入后台,但使用后该进程就会处于停止状态(Stopped)


67c1d6d91fbc4ecf8d4073879f8c82ec.png


使用bg命令,可以让某个停止的作业在后台继续运行(Running)


其本质就是给该作业的进程组的每个进程发SIGCONT信号

e37846c0e2304aef9d88fbac01ea7007.png



1.4.3 ps命令查看指定的选项

使用ps命令时携带-o选项,可以查看指定的信息


b4942980dbc240eab4fdfeb703493230.png


当用Xshell或是终端登录时,本质都是先创建一个bash进程,整体称之为一个会话(所有的命令行的进程都是bash的子进程),所有的命令行启动的任务都是在对应的会话内运行


实际每一次登录的过程都是新建会话的过程,同一个会话中的所有进程的SESS是相同的


注意: ps命令是系统级的命令,能查看所有进程的信息,如ps -axj,只不过-o选项只查看当前会话的进程信息


二、守护进程

2.1 概念

守护进程也称精灵进程(Daemon),是运行在后台的一种特殊进程,独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件


守护进程是用处广泛,Linux的大多数服务器都是用守护进程实现的,如Internet服务器inetd,Web服务器httpd等。同时守护进程完成许多系统任务,如作业规划进程crond等


Linux系统启动时会启动很多系统服务进程,这些系统服务进程没有控制终端,不能直接和用户交互。其他进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,一直在运行,这种进程被称为守护进程(Daemon),且守护进程一般采用以d结尾的名字


2.2 守护进程的查看

使用ps axj命令查看系统中的进程:


参数a表示不仅列出当前用户的进程,也列出所有其他用户的进程

参数x表示不仅列出有控制终端的进程,也列出所有无控制终端的进程

参数j表示列出与作业控制相关的信息

TPGID处为-1的都是没有控制终端的进程,即守护进程


7087b4e2b9a4463daa6c208bba346c99.png


在COMMAND一列用[ ]括起来的名字表示内核线程,在内核里创建,没有用户空间代码,因此没有程序文件名和命令行,通常采用以k开头的名字,表示Kernel


2.3 创建守护进程

2.3.1 原生创建守护进程

守护进程的创建步骤如下:


设置文件掩码为0

  1. 忽略SIGCHLD、SIGPIPE等信号
  2. fork后终止父进程,确保子进程不为进程组组长
  3. 创建新会话
  4. 再次fork,终止父进程,保持子进程不是会话首进程,从而保证后续不会和其他终端相关联
  5. 更改工作目录为根目录
  6. 将标准输入、标准输出、标准错误重定向到/dev/null

相关说明:


  1. 子进程会继承父进程的掩码。将文件掩码设置为0,保证后续守护进程创建出来的文件的权限符合预期
  2. 忽略SIGCHLD、SIGPIPE,确保守护进程不会因为子进程或管道通信而崩溃
  3. 调用setsid创建新会话时,要求调用进程不能是进程组组长,但是在命令行上启动多个进程协同完成某种任务时,第一个被创建出来的进程就是组长进程,因此需fork创建子进程,让子进程调用setsid创建新会话并继续执行后续代码,而父进程直接退出即可
  4. 调用setsid让当前进程自成会话,与当前bash脱离关系(创建守护进程的核心)
  5. 守护进程不能直接和用户交互,也就没有必要再打开某个终端了,而打开一个终端需要是会话首进程,为了防止守护进程打开终端,再次fork创建子进程并让子进程继续执行后续代码,由于子进程不是会话首进程,也就没有能力打开其他终端了,而父进程直接退出即可(防御性编程,该操作不是必须的)
  6. 一般会将守护进程的工作目录设置为根目录,便于让守护进程以绝对路径的形式访问某种资源(该操作不是必须的)
  7. 守护进程不能直接和用户交互,即守护进程已经与终端去关联了,因此一般会将守护进程的标准输入、标准输出以及标准错误都重定向到/dev/null,/dev/null是一个字符文件(设备),通常用于屏蔽/丢弃输入输出信息(该操作不是必须的)
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void DaemonSelf()
{
    //1. 设置文件掩码
    umask(0);
    //2. 忽略SIGCHLD、SIGPIPE信号
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    //3. fork后终止父进程,保证子进程不为进程组组长
    if(fork() > 0) exit(0);
    //4. 创建新会话
    setsid();
    //5. fork后终止父进程,保持子进程不是会话首进程,从而保证后续不会再和其他终端相关联
  //(不是必须的,防御性编程)
    if(fork() > 0) exit(0);
    //6. 更改工作目录为根目录
    chdir("/");
    //7. 标准输入、标准输出、标准错误重定向到/dev/null
    int devNull = open("/dev/null", O_RDWR);
    if(devNull > 0) {
        dup2(0, devNull);
        dup2(1, devNull);
        dup2(2, devNull);
        close(devNull);
    }
}


运行代码,用ps命令查看该进程,会发现该进程的TPGID为-1,TTY显示?,也就意味着该进程已经与终端去关联了。还可以发现该进程的PID与其PGID和SID是不同的,也就是说该进程既不是组长进程也不是会话首进程


6f2edc6dd3694ce490e1ad10313e8bb5.png


该进程的SID与bash进程的SID是不同的,即不属于同一个会话


d9558f35cfe24b8d8240f3967df485b1.png


使用 ls /proc/进程ID -al 命令,可以看到该进程的工作目录已经成功改为了根目录


420bb8a6a3d34e038d9590792de27b06.png


使用 ls /proc/进程ID/fd -al 命令,可以看到该进程的标准输入、标准输出以及标准错误也成功重定向到了 /dev/null


50de61f5475d46c78d1cf50bb7e1e113.png


2.3.2 daemon函数创建守护进程

实际当我们创建守护进程时可以直接调用daemon接口进行创建,daemon函数的函数原型如下:


int daemon(int nochdir, int noclose);

若参数nochdir为0,则将守护进程的工作目录该为根目录,否则不做处理

若参数noclose为0,则将守护进程的标准输入、标准输出以及标准错误重定向到/dev/null,否则不做处理

#include <unistd.h>
int main()
{
    daemon(0, 0);
    while (1);
    return 0;
}

调用daemon函数创建的守护进程与自主创建的守护进程差别不大,唯一区别就是daemon函数创建出来的守护进程,既是组长进程也是会话首进程

3042a991384c41d39cbc733580fc8eac.png



系统实现的daemon函数没有防止守护进程打开终端,上面自主实现的反而比系统更加完善

目录
相关文章
|
3月前
|
存储 监控 Linux
|
Linux Shell C语言
【Linux】Linux任务管理与守护进程
【Linux】Linux任务管理与守护进程
|
数据采集 Shell Linux
[oeasy]python0033_任务管理_jobs_切换任务_进程树结构_fg
[oeasy]python0033_任务管理_jobs_切换任务_进程树结构_fg
111 0
[oeasy]python0033_任务管理_jobs_切换任务_进程树结构_fg
|
5月前
|
监控 Linux 应用服务中间件
探索Linux中的`ps`命令:进程监控与分析的利器
探索Linux中的`ps`命令:进程监控与分析的利器
126 13
|
4月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
4月前
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
166 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
3月前
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。
|
4月前
|
存储 缓存 安全
【Linux】冯诺依曼体系结构与操作系统及其进程
【Linux】冯诺依曼体系结构与操作系统及其进程
171 1
|
4月前
|
小程序 Linux
【编程小实验】利用Linux fork()与文件I/O:父进程与子进程协同实现高效cp命令(前半文件与后半文件并行复制)
这个小程序是在文件IO的基础上去结合父子进程的一个使用,利用父子进程相互独立的特点实现对数据不同的操作
105 2
|
4月前
|
SQL 自然语言处理 网络协议
【Linux开发实战指南】基于TCP、进程数据结构与SQL数据库:构建在线云词典系统(含注册、登录、查询、历史记录管理功能及源码分享)
TCP(Transmission Control Protocol)连接是互联网上最常用的一种面向连接、可靠的、基于字节流的传输层通信协议。建立TCP连接需要经过著名的“三次握手”过程: 1. SYN(同步序列编号):客户端发送一个SYN包给服务器,并进入SYN_SEND状态,等待服务器确认。 2. SYN-ACK:服务器收到SYN包后,回应一个SYN-ACK(SYN+ACKnowledgment)包,告诉客户端其接收到了请求,并同意建立连接,此时服务器进入SYN_RECV状态。 3. ACK(确认字符):客户端收到服务器的SYN-ACK包后,发送一个ACK包给服务器,确认收到了服务器的确
190 1

热门文章

最新文章

相关实验场景

更多