Linux守护进程

Linux守护进程_第1张图片

"忍耐的灵魂啊,安静地运转吧~"


        我们先来看看这个场景。这是一个常见的基于TCP套接字的网络服务器,服务端接收客户端发送的消息,收到后并向echo回响给客户端。

Linux守护进程_第2张图片        对于Linux而言,终端只能有一个前台进程,这也是为什么当我们在服务端一侧启动服务时,继续输入诸如ls\pwd\which等命令时,bash(shell)没有作任何响应。Linux守护进程_第3张图片

         现在我们将服务端的窗口关闭后,可以发现的是,客户端就自动退出了。

Linux守护进程_第4张图片

         这是为什么呢?上述图片描述了什么呢? SID又是什么呢??我们又该如何解决这个问题呢,让我们即便会话窗口退出,也不影响服务器的运行?

——前言


一、 Xshell远端登录和断开做了些什么?

Linux守护进程_第5张图片

        回答上面的问题并不难,我们使用的Xshell向远端建立链接时,会为用户自动生成一个名为会话的窗口,而SID指的就是会话ID。可以到,图示的打开的三个会话窗口,都具有不同的会话ID。

         

二、 如何理解Linux下的作业?

        我们来看看下面一段代码的例子,使用匿名管道没有别的特殊用意。

sleep 10000 | sleep 20000 | sleeep 30000

Linux守护进程_第6张图片

         启动程序后面加"&",意味着让该程序启动后,运行在后台。此时我们用jobs可以查看这个工作在后台的进程。

Linux守护进程_第7张图片

可是我们又该如何理解前、后台进程?

        当我们将上述的三个进程在后台进行运行时,这三个用匿名管道连接起来的进程看似毫不相干,但它们都同属于一个进程组(PGID)! 

        这个代码里创建的所有进程都在"协同"完成一件事情——休眠(sleep)。

        为此,我们把正在执行的一个或多个相关的进程被称为"作业"

Linux守护进程_第8张图片

         我们输入jobs命令,可以查看后台进程的任务。我们可以通过 fg\bg 命令来回将一个作业进行前、后台状态的切换。

Linux守护进程_第9张图片

Linux守护进程_第10张图片


       

        对!你上面说的我都理解,当使用Xshell进行远端登录时,会为不同的窗口创建不同的session_Id,而一旦这个会话窗口关闭,其实也就意味着该窗口内运行着的前、后台也会进程关闭。但你还是没有解决服务器不依赖会话的运行的问题。

        

三、 守护进程

(1) 初始守护进程

        守护进程(也叫做精灵进程)deamon,是生存期较长的一种进程,它们常常在系统自举时启动,仅仅在系统关闭时终止。因为它们没有终端,也就意味着它们是运行在后台的。

        在Linux中存在很多守护进程,它们执行事务活动。

        我们使用命令:

-a: 显示由其他用户所拥有的进程状态
-x: 显示没有控制终端的进程状态
-j: 显示与作业有关的信息
ps -axj

Linux守护进程_第11张图片

        其中有意义的列标为,父进程ID,进程ID,进程组ID,会话ID,终端名称,终端进组ID,用户ID,命令字符串。 

        TPGID为-1的为守护进程。

为什么使用守护进程?

        在linux系统中,每个系统与用户进行交流的界面成为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端被称为这些进程的控制终端。当用户断开连接,会话关闭,终端关闭后,该终端内的进程也会随之关闭。

        然而,守护进程却可以突破这种限制,因为守护进程是没有终端的。它脱离终端的目的是为了避免进程在运行的过程中的信息,并且进程也不会被任何终端所产生的终端信息所打断。Linux守护进程_第12张图片

       

(2) 守护进程实现

实现流程:

Linux守护进程_第13张图片

实现:

// #pragma once

#include 
#include 
#include 
#include 

#include 
#include 
#include 

#define DAEMON_FILE "daemonlog.txt"

void daemonSelf(const char* currPath = NULL)
{
    // 1.创建子进程
    if(fork() > 0) exit(0);

    // 2.另起会话 本质就是一个孤儿进程
    pid_t id = setsid();
    // 断死不会错误
    assert(id != -1);

    // 3.关闭终端 
    // 输出信息到daemonlog.txt
    int fd = open(DAEMON_FILE,O_RDWR);
    if(fd >= 0)
    {
        dup2(fd,0);
        dup2(fd,1);
        dup2(fd,2);

        close(fd);
    }   
    else
    {
        close(0);
        close(1);
        close(2);
    }
    char buffer[] = "dup2重定向完毕\n";
    write(fd,buffer,sizeof(buffer));

    // 4.更改工作路径
    if(currPath) chdir(currPath);

    // 5.文件掩码
    umask(0);

    char buffer2[] = "守护进程创建完成\n";
    write(fd,buffer2,sizeof(buffer2));

}

int main()
{   
    printf("开始创建\n");
    daemonSelf();
    return 0;
}

               

        此时我们在命令行运行该程序,通过ps 查询该进程的 TPGID 为-1,验证是为守护进程。

Linux守护进程_第14张图片

         我们再将左端的(创建端)session窗口关闭后重新链接,可以得出,此进程自此不受用户远程登录、断开连接的影响,自成会话。

Linux守护进程_第15张图片

        但这并不意味着这个进程就可以为所欲为了,我们也可以在命令行终端输入kill -9 发送信号"杀死"该进程。

Linux守护进程_第16张图片

总结:

        守护进程常常用作服务器进程,一般而言服务器是等待客户进程与其进行联系的一个进程。守护进程在大多数Linux中是一直运行的,因为守护进程没有终端,我们可以选择将进程运行信息通过文件打印出来。

Linux守护进程_第17张图片

你可能感兴趣的:(linux小黑板,Linux,linux,服务器)