什么是守护进程?

什么是守护进程?在了解守护进程之前,需要先知道什么是什么是终端?什么是作业?什么是进程组?什么是会话?在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个

大家好,又见面了,我是你们的朋友全栈君。

在了解守护进程之前,需要先知道什么是什么是终端?什么是作业?什么是进程组?什么是会话?

在 Linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。

守护进程就是一个生存周期较长,独立于控制终端并且周期性执行某种任务的进程。之所以要脱离终端,就是为了防止进程运行过程中被任何终端信息所打断。

所以,要创建守护进程,我们就要将这个进程脱离终端。

shell分前后台作业来控制的不是进程而是作业。一个作业由多个进程组成。Shell可以运行一个前台作业和任意多个后台作业,称为作业控制。bash就是一个独立的作业。

进程组是一个或多个进程的集合,每个进程除了有一个PID以外,还有一个PGID。PGID就是组长的PID。进程组通常和一个作业相关联,可以接收来自同一个终端的信号。

当然,进程组和作业也并不是完全等价的两个概念:如果作业中某个进程有创建了新的子进程,该子进程不属于作业,但属于该进程组。

会话(Session)是一个或多个进程组的集合。一个会话可以有一个控制终端。一个会话中,有一个前台作业和若干个后台作业。会话SID是会话手进程的PID。

为什么只能运行一个前台作业?当我们在前台新起了一个作业,shell就被提到了后台,因此shell就没有办法再继续接受我们的指令并且解析运行了。但是如果前台进程退出了,shell就会有被提到前台来,就可以继续接受我们的命令并且解析运行。

那么,如何来切断进程和终端的关系呢?

首先,调用 setsid() 使子进程成为新的会话组长。setsid() 调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。

调用setsid()有一个前提,就是该进程不能是一个组长进程,因此需要先fork并且杀死父进程,setsid ()的调用者是子进程。

接下来,要禁止进程重新打开控制终端。能打开控制终端的进程一定是进程组组长,因此我们需要再次fork(),并且杀死父进程,留下的子进程就不再是话首进程和进程组组长。于是,这个子进程也不再拥有打开终端的权限,至此,我们彻底切断了该进程和终端的联系。

最后,要关闭打开的文件描述符,或者对打开的文件描述符进行重定向。因为进程会继承从父进程那里的文件描述符,如果不关闭,会浪费系统的资源。

如果想改变该进程的所在目录,可以调用chdir(“/”) 将该守护进程转移到根目录。

如果该守护进程有子进程,那么守护进程需要等待子进程退出,否则子进程会变成僵尸进程。为了减少该守护进程的负担,防止其回收子进程对服务器并发性能的影响,可以使用signal(SIGCHLD, SIG_IGN) 对SIGCHLD忽略。这样就可以防止僵尸进程产生。

#include <unistd.h>   
#include <signal.h>   
#include <fcntl.h>  
#include <sys/syslog.h>  
#include <sys/param.h>   
#include <sys/types.h>   
#include <sys/stat.h>   
#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
  
int init_daemon(void)  
{   
    int pid;   
    int i;  
      
    // 1)屏蔽一些控制终端操作的信号  
    signal(SIGTTOU,SIG_IGN);   
    signal(SIGTTIN,SIG_IGN);   
    signal(SIGTSTP,SIG_IGN);   
    signal(SIGHUP ,SIG_IGN);  
   
    // 2)在后台运行  
    if( pid=fork() ){ // 父进程  
        exit(0); //结束父进程,子进程继续  
    }else if(pid< 0){ // 出错  
        perror("fork");  
        exit(EXIT_FAILURE);  
    }  
      
    // 3)脱离控制终端、登录会话和进程组  
    setsid();    
      
    // 4)禁止进程重新打开控制终端,这是一种防御性编程,是可选的一步
    if( pid=fork() ){ // 父进程  
        exit(0);      // 结束第一子进程,第二子进程继续(第二子进程不再是会话组长)
     
    }else if(pid< 0){ // 出错  
        perror("fork");  
        exit(EXIT_FAILURE);  
    }    
      
    // 5)关闭打开的文件描述符  
    // NOFILE 为 <sys/param.h> 的宏定义  
    // NOFILE 为文件描述符最大个数,不同系统有不同限制  
    for(i=0; i< NOFILE; ++i){  
        close(i);  
    }  
      
    // 6)改变当前工作目录  
    chdir("/tmp");   
      
    // 7)重设文件创建掩模,因为进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取权限。
    umask(0);    
      
    // 8)处理 SIGCHLD 信号  
    signal(SIGCHLD,SIG_IGN);  
      
    return 0;   
}   
  
int main(int argc, char *argv[])   
{  
    init_daemon();  
      
    while(1);  
  
    return 0;  
} 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/154705.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • ifconfig 与 ip addr 命令详解 – 学习/实践

    ifconfig 与 ip addr 命令详解 – 学习/实践1.应用场景 主要用于了解学习,掌握使用IP地址相关知识, 如何查看IP信息,以及各个参数代表的含义 2.学习/操作 1.文档阅读 网络协议概论|Laravel学院-不定期分享之ifconfig与ipaddr命令详解 2.整理输出 2.1如何查看机器的IP地址 我们在Linux系统查看IP地址通常有以下两种方式: 1)ifconfig 2)ipaddr

    2022年7月27日
  • 你为什么从java开发转大数据? 大数据方向能走的更远吗?

    你为什么从java开发转大数据? 大数据方向能走的更远吗?今天在知乎上看到一个问题,问:你为什么从java开发转大数据方向?大数据方向能走的更远吗?我是从java开发转到大数据开发的。看到这个问题,想到了几年前,学校刚毕业时,在传统行业做ja…

    2022年7月7日
  • redis分布式锁的应用场景_分布式锁redis实现方式

    redis分布式锁的应用场景_分布式锁redis实现方式RedLock分布式锁 基于Redis实现分布式锁的方式名叫Redlock 安全特性:互斥访问,即永远只有一个client能拿到锁 避免死锁:最终client都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的clientcrash了或者出现了网络分区(两个完全不连通的区域,美国的网咱们登不上去) 容错性:只要大部分Redis节点存活就可以正常提供服务 Redis集群及应用场景热点数据存取数据优先从Redis操作,如果不存在再从文

    2022年9月8日
  • 使用Fastjson生成Json字符串少字段属性(数据丢失)「建议收藏」

    在开发中经常要使用到fastJson来转换对象为json 串,但是最近发现在一个对象转换的时候,总是丢失了一个字段的值,(数据丢失).就很纳闷。到网上找了很多方法总是不行,最后总算是在一篇博文中看到问题的关键!现在整理如下,希望可以帮助到更多的人。package per.eblink.pojo; public class Node { private String id

    2022年2月24日
  • C/C++读写文本文件、二进制文件「建议收藏」

    C/C++读写文本文件、二进制文件「建议收藏」C语言文本文件读写方式;C语言二进制文件读写方式;CPP文本文件读写方式;CPP二进制文件读写方式;

    2022年6月1日
  • java 自定义类加载器_JAVA中如何使用应用自定义类加载器「建议收藏」

    java 自定义类加载器_JAVA中如何使用应用自定义类加载器「建议收藏」最近在研究javaCLASSLOADING技术,已实现了一个自定义的加载器。对目前自定义加载器的应用,还在探讨中。下面是自定义的CLASSLOADER在JAVA加密解密方面的一些研究。JAVA安全JAVA是解释执行的语言,对于不同的操作平台都有相应的JVM对字节码文件进行解释执行。而这个字节码文件,也就是我们平时所看到的每一个.class文件。这是我们大家都知道的常识,也就是由.java文件,…

    2022年9月6日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号