守护进程的编写

目录

  • 守护进程的编写

    • 一,普通进程
    • 二,守护进程

守护进程的编写

ps: 参考资料:linux C++通讯架构实战 卷1

一,普通进程

查看进程

ps -eo pid,ppid,sid,tty,pgrp,comm,stat,cmd | grep -E 'bash|PID|nginx'
  • 这种进程都有各自对应的终端,终端退出,该进程也就退出,它的父进程是一个bash
  • 终端被占用,你输入命令没有作用
  • 如果放到后台(bg), 输入命令有用了,但是终端关闭进程仍然会退出

二,守护进程

定义:一种长期在后台运行的进程,不与任何终端关联

  • Linux本身是有很多守护进程默默运行着。查看ps -efj

    • ppid = 0 内核进程,跟随系统,生命周期贯穿这个系统。
    • cmd 带 [ ] 的是内核守护进程
    • 老祖init,也是系统守护进程,它负责启动各运行层次特定的系统服务;所以很多进程的PPID是init。而且这个init也负责收养孤儿进程;
    • cmd列中名字不带[]的普通守护进程(用户级守护进程)
  • 共同特点
    • 大多数守护进程都是以超级 用户特权运行的;
    • 守护进程没有控制终端,TT这列显示?
    • 内核守护进程以无控制终端方式启动
    • 普通守护进程可能是守护进程调用了setsid的结果(无控制端);

编写规则

  • 调用umask(0);

    • umask是个函数,用来限制(屏蔽)一些文件权限的。
  • fork()一个子进程(脱离终端)出来,然后父进程退出( 把终端空出来,不让终端卡住);固定套路
    • fork()的目的是想成功调用setsid()来建立新会话,目的是子进程有单独的sid;
    • 而且子进程也成为了一个新进程组的组长进程;同时,子进程不关联任何终端了;

在编写前还需要知道一些相关概念

  • 文件描述符

    • 当你打开一个存在的文件或者创建一个新文件,操作系统都会返回这个文件描述符(其实就是代表这个文件的),后续对这个文件的操作的一些函数,都会用到这个文件描述符作为参数;
    • linux中三个特殊的文件描述符,数字分别为0,1,2
      • 0:标准输入【键盘】,对应的符号常量叫STDIN_FILENO
      • 1:标准输出【屏幕】,对应的符号常量叫STDOUT_FILENO
      • 2:标准错误【屏幕】,对应的符号常量叫STDERR_FILENO
    • 类Unix操作系统,默认从STDIN_FILENO读数据,向STDOUT_FILENO来写数据,向STDERR_FILENO来写错误;
    • 万物皆文件
    • 你程序一旦运行起来,这三个文件描述符0,1,2会被自动打开(自动指向对应的设备);
//文件描述符虽然是数字,但是,如果我们把文件描述符直接理解成指针(指针里边保存的是
//地址——地址说白了也是个数字);
write(STDOUT_FILENO,"aaaabbb",6);
  • 输入输出重定向

    • 以前老写的freopen应该是同一个原理。
    • 在Linux命令行中的 > < 可以重定向输出
  • 空设备 【 /dev/null 】
    • 一个特殊的文件设备,重定向过去的东西都会被吸收(黑洞)

  • 守护进程不会收到的信号:内核发给你,另外的进程发给你的

    • SIGHUP信号

      • 守护进程不会收到来自内核的 SIGHUP 信号; 潜台词就是 如果守护进程收到了 SIGHUP信号,那么肯定是另外的进程发给你的;
      • 很多守护进程把这个信号作为通知信号,表示配置文件已经发生改动,守护进程应该重新读入其配置文件;
    • SIGINT、SIGWINCH信号
      • 守护进程不会收到来自内核的 SIGINT(ctrl+C),SIGWINCH(终端窗口大小改变) 信号;
  • 守护进程和后台进程的区别
    • 守护进程和终端不挂钩;后台进程能往终端上输出东西(和终端挂钩);
    • 守护进程关闭终端时不受影响,守护进程会随着终端的退出而退出;

案例代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>

//创建守护进程
//创建成功则返回1,否则返回-1
int ngx_daemon()
{
    int  fd;

    switch (fork())  //fork()子进程
    {
    case -1:
        //创建子进程失败,这里可以写日志......
        return -1;
    case 0:
        //子进程,走到这里,直接break;
        break;
    default:
        //父进程,直接退出
        exit(0);
    }

    //只有子进程流程才能走到这里
    if (setsid() == -1)  //脱离终端,终端关闭,将跟此子进程无关
    {
        //记录错误日志......
        return -1;
    }
    umask(0); //设置为0,不要让它来限制文件权限,以免引起混乱

    fd = open("/dev/null", O_RDWR); //打开黑洞设备,以读写方式打开
    if (fd == -1)
    {
        //记录错误日志......
        return -1;
    }
    if (dup2(fd, STDIN_FILENO) == -1) //先关闭STDIN_FILENO[这是规矩,已经打开的描述符,动他之前,先close],类似于指针指向null,让/dev/null成为标准输入;
    {
        //记录错误日志......
        return -1;
    }

    if (dup2(fd, STDOUT_FILENO) == -1) //先关闭STDIN_FILENO,类似于指针指向null,让/dev/null成为标准输出;
    {
        //记录错误日志......
        return -1;
    }

     if (fd > STDERR_FILENO)  //fd应该是3,这个应该成立
     {
        if (close(fd) == -1)  //释放资源这样这个文件描述符就可以被复用;不然这个数字【文件描述符】会被一直占着;
        {
            //记录错误日志......
            return -1;
        }
    }

    return 1;
}

int main(int argc, char *const *argv)
{
    if(ngx_daemon() != 1)
    {
        //创建守护进程失败,可以做失败后的处理比如写日志等等
        return 1;
    }
    else
    {
        //创建守护进程成功,执行守护进程中要干的活
        for(;;)
        {
            sleep(1); //休息1秒
            printf("休息1秒,进程id=%d!\n",getpid()); //你就算打印也没用,现在标准输出指向黑洞(/dev/null),打印不出任何结果【不显示任何结果】
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Q1143316492/p/10745712.html

时间: 2024-11-07 03:53:42

守护进程的编写的相关文章

服务器程序后台化以及守护进程的编写规范

一般的服务器程序都是以后台进程(守护进程)的方式运行,那么要如何使得服务器进程后台化呢? 下面介绍守护进程的编写遵循的步骤: 1. 创建子进程,关闭父进程:2. 设置文件权限掩码.当进程创建新文件(使用open(const char *pathname, int flags, mode_t mode)系统调用时,文件的权限将是mode&0777: 3. 创建新会话,设置本进程为进程组的首领: 4. 切换工作目录: 5. 关闭标准输入设备.标准输出设备和标准错误输出设备: 6. 关闭其他已经打开的

编写Linux/Unix守护进程

原文: http://www.cnblogs.com/haimingwey/archive/2012/04/25/2470190.html 守护进程在Linux/Unix系统中有着广泛的应用.有时,开发人员也想把自己的程序变成守护进程.在创建一个守护进程的时候,要接触到子进程.进程组.会晤期.信号机制.文件.目录和控制终端等多个概念.因此守护进程还是比较复杂的,在这里详细地讨论Linux/Unix的守护进程的编写,总结出八条经验,并给出应用范例. 编程要点 1.屏蔽一些有关控制终端操作的信号.防

linux下python守护进程编写和原理理解

原文地址: http://www.01happy.com/linux-python-daemon/ 守护进程英文为daemon,像httpd.mysqld.vsftpd最后个字母d其实就是表示daemon的意思. 守护进程的编写步骤: fork子进程,而后父进程退出,此时子进程会被init进程接管. 修改子进程的工作目录.创建新进程组和新会话.修改umask. 子进程再次fork一个进程,这个进程可以称为孙子进程,而后子进程退出. 重定向孙子进程的标准输入流.标准输出流.标准错误流到/dev/n

Unix网络编程代码 第13章 守护进程和inetd超级服务器

1. 概述 守护进程是在后台运行且不与任何控制终端关联的进程.unix系统通常有很多守护进程在后台运行,执行不同的管理任务.    守护进程没有控制终端通常源于它们由系统初始化脚本启动.然而守护进程也可能从某个终端由用户在shell提示符下键入命令行启动,这样的守护进程必须亲自脱离与控制终端的关联,从而避免与作业控制,终端会话管理,终端产生信号等发生任何不期望的交互,也可以避免在后台运行的守护进程非预期的输出到终端.    守护进程有多种启动方法:    1.在系统启动阶段,许多守护进程由系统初

孤儿进程、僵尸进程和守护进程

维基百科的解释中: 在操作系统领域中,孤儿进程指的是在其父进程执行完成或被终止 后仍继续运行的一类进程. 在类UNIX系统中,僵尸进程是指完成执行(通过 exit 系统调用,或运行时发生致命错误或收到终止信号所致)但在操作系统的进程表中仍然有一个表项(进程控制块PCB),处于"终止状态 "的进程. 在一個多工的電腦作業系統中,守护进程(英语:daemon,英语发音:/?di?m?n/或英语发音:/?de?m?n/)是一種在后台执行的电脑程序. 此类程序会被以进程的形式初始化. 守护进程

Linux多任务编程之七:Linux守护进程及其基础实验(转)

来源:CSDN  作者:王文松  转自Linux公社 ------------------------------------------------------------------------------------------------ 守护进程概述 守护进程,又叫daemon进程(不知怎的,我突然想起来吸血鬼日记中的达蒙了,很好看的美剧),是Linux中的后台服务进程. 他是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或者等待处理某些发生的事件.守护进程常常在系统

python守护进程

假如写一段服务端程序,如果ctrl+c退出或者关闭终端,那么服务端程序就会退出,于是就想着让这个程序成为守护进程,像httpd一样,一直在后端运行,不会受终端影响. 守护进程英文为daemon,像httpd,mysqld,最后一个字母d其实就是表示daemon的意思. 守护进程的编写步骤: fork子进程,然后父进程退出,此时子进程会被init进程接管. 修改子进程的工作目录,创建新进程组合新会话,修改umask. 子进程再次fork一个进程,这个进程可以称为孙子进程,然后子进程退出. 重定向孙

linux 创建守护进程的相关知识

linux 创建守护进程的相关知识 http://www.114390.com/article/46410.htm linux 创建守护进程的相关知识,这篇文章主要介绍了linux 创建守护进程的相关知识,需要的朋友可以参考下 关键字:linux.守护进程 创建子进程,父进程退出 这是编写守护进程的第一步.由于守护进程是脱离控制终端的,因此,完成第一步后就会在Shell终端里造成一程序已经运行完毕的假象.之后的所有工作都在子进程中完成,而用户在Shell终端里则可以执行其他命令,从而在形式上做到

Linux下一个简单守护进程的实现 (Daemon)

在Linux/UNIX系统引导的时候会开启很多服务,这些服务称为守护进程(也叫Daemon进程).守护进程是脱离于控制终端并且在后台周期性地执行某种任务或等待处理某些事件的进程,脱离终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的中断信息所终止. 创建守护进程的一般步骤: (1) 创建子进程,退出父进程 为了脱离控制终端需要退出父进程,之后的工作都由子进程完成.在Linux中父进程先于子进程退出会造成子进程成为孤儿进程,而每当系统发现一个孤儿进程时,就会自动由