Linux守护进程

一、基本概念

  • 守护进程: 后台执行,运行周期长,无需和用户交互
  • 会话:打开一个终端,就会随之产生一个会话
  • 会话首进程:会话中运行的第一个进程,一般来说是/usr/bin/bash
  • 进程组:对于单进程程序,进程组中只有一个进程;对于多进程程序,进程组有多个进程
  • 组长进程:进程组的第一个进程

在这里插入图片描述
对于服务而言,不应该随着终端的结束而结束,启动了服务就需要一直在后台运行。我们可以新建一个会话,然后把服务对应的进程移动到新的会话。

而用于建立新会话的进程需要是普通的组员进程(不能是组长进程,更不能是会话首进程),因为会使用进程的id作为会话的id,如果原来这个进程就是一个会话首进程,那么这个进程的id已经标识了一个会话,再使用这个进程id标识会话就会重复

1. 会话id == 会话首进程id

int main(){
    printf("sid=%d, pid=%d\n", getsid(0), getpid());
    return 0;
}

在这里插入图片描述
2. 组长进程id == 进程组id

int main(){
	// 会话id,进程id,进程组id
    printf("sid=%d, pid=%d, gid=%d\n", getsid(0), getpid(), getpgrp());
    return 0;
}

在这里插入图片描述

3. 父子进程同一进程组,同一会话

int main(){
    pid_t pid = fork();
    if(pid == 0){
        printf("子进程:sid=%d, pid=%d, gid=%d\n", getsid(0), getpid(), getpgrp());
    }else{
        printf("父进程:sid=%d, pid=%d, gid=%d\n", getsid(0), getpid(), getpgrp());
    }
    return 0;
}
父进程:sid=303, pid=1106, gid=1106
子进程:sid=303, pid=1107, gid=1106

进程组什么时候消失?
进程组中最后一个进程消失的时候进程组就消失,而不是组长进程结束就消失

二、创建守护进程

面试可能问到的编程流程:

  1. fork():产生子进程后,退出父进程
  2. setsid():创建新的会话,使得原来的进程脱离会话,进入新的会话,成为会话首进程
  3. fork():产生孙子进程后,退出儿子进程。这一步可省略,使得留下的孙子进程没有会话首进程的身份,这样留下的进程就不会和某个终端关联起来,起保险作用
  4. 为了守护进程能长久运行做准备,由于不用stdin、stdout等,关闭所有不用的描述符
  5. 由于守护进程运行时间长,所以需要把该进程的工作目录移动至/目录,防止守护进程占用长期占用工作空间,其他进程无法使用
  6. 若产生子进程,需要处理僵尸进程。因为父进程一直不结束,也不处理,就会产生大量僵尸进程
  7. umask(0),掩码设置为0后,创建出来的文件权限就是当前用户所具有的全部权限

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>

void set_demon(){
    pid_t pid = fork();
    if(pid != 0){
        // 退出父进程
        exit(0);
    }
    // 创建新会话
    setsid();
    // 退出当前会话的首进程,孙子进程成为会话唯一进程
    pid = fork();
    if(pid != 0){
        // 退出父进程
        exit(0);
    }
    // 设置工作路径
    chdir("/");
    umask(0);
    // 拿到打开文件描述符的最大数量
    int open_size = getdtablesize();
    for(int i = 0; i < open_size; i++){
        // 关闭所有能打开的描述符
        close(i);
    }
}


int main(){
    set_demon(); // 当前进程设置为守护进程
    while(1){
    	// 任何用户都可在/tmp下创建文件
        FILE* fp = fopen("/tmp/guard_process.log", "a");
        if(NULL == fp){
            break;
        }
        time_t tv;
        // 获取从1970年经过的秒数
        time(&tv);
        fprintf(fp, "%s", asctime(localtime(&tv)));
        fclose(fp); // 这里不关闭,下次循环再fopen,返回的fp不一样,日志文件也无法写入新的信息
        sleep(5);
    }
    return 0;
}

在这里插入图片描述
看日志文件,一般使用:tail -f guard_process.log,tail命令动态追踪文件并打印到终端

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bugcoder-9905

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值