Linux daemon进程原理与使用

什么情况下用daemon进程

生产环境下,除了我们ssh登录上去,然后手动跑的那部分以外,其他都是自动运行的,这些大部分都应该是后台执行的。如何才能后台执行呢?

  1. nohup ./XXX &
  2. 由系统的其他daemon进程启动。这样的话,你的程序是它的子进程,跟终端没关系。退出终端也不会导致进程退出。如写在crontab里。
  3. 写成daemon程序,可以手动执行,退出终端时程序不退出。

如何选择呢?

(1)首先,清理过期日志这一类需求,可以写一个死循环一直运行,也可以写在crontab里,每次执行完就退出(如果每分钟一次可以满足的话);

(2)crontab的需要接受最多1分钟的时延,如果实时性要求更高一些,那么就需要考虑写个死循环了,这个程序可以由crontab来start和restart,只有在挂了重启时才会出现1分钟时延;

(3)服务不能中断的(nginx、redis、apache,所有在线服务),一般都是daemon程序。但理论上用(2)似乎也可以;当然这两者细节上有很多区别。

怎么用daemon进程

linux C/C++可以直接调用int daemon(int, int)函数,不需要自己重新实现。

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage: $0 no_ch_dir no_close_fd\n");
        exit(0);
    }

    int no_ch_dir = atoi(argv[1]);
    int no_close_fd = atoi(argv[2]);

    std::cout << "main pid : " << getpid() << std::endl;
    std::cout << "main parent pid : " << getppid() << std::endl;
    std::cout << "main pwd : " << get_current_dir_name() << std::endl;
    if (daemon(no_ch_dir, no_close_fd) != 0) {
        // 一般都用daemon(0,0)
        // 成功返回0,失败返回-1
        // daemon(0,0):chdir到/,关闭0,1,2描述符。
        std::cout << "stdout: daemon = -1" << std::endl;
        std::cerr << "stderr: daemon = -1" << std::endl;
        return 1;
    }
    std::cout << "stdout: daemon = 0" << std::endl;
    std::cerr << "stderr: daemon = 0" << std::endl;

    std::cout << "sub pid : " << getpid() << std::endl;
    std::cout << "sub parent pid : " << getppid() << std::endl;
    std::cout << "sub pwd : " << get_current_dir_name() << std::endl;
    while (1);
    return 0;
}```
编译运行:

[[email protected] ~]g++test1.cc?otest1[chenming@localhost ] ./test1

Usage: 0nochdirnoclosefd[chenming@localhost ] ./test1 0 0

main pid : 7896

main parent pid : 7573

main pwd : /home/chenming

[[email protected] ~]ps?ef|greptest194:chenming78647573516:09pts/000:00:16vimtest1.cc95:chenming789719316:14?00:00:18./test10097:chenming78997573716:15pts/000:00:00grep?inE–colortest1[chenming@localhost ] ll /proc/7897/fd

total 0

lrwx——. 1 chenming chenming 64 May 1 16:15 0 -> /dev/null

lrwx——. 1 chenming chenming 64 May 1 16:15 1 -> /dev/null

lrwx——. 1 chenming chenming 64 May 1 16:15 2 -> /dev/null

[[email protected] ~]$ lsof -p 7897

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME

test1 7897 chenming cwd DIR 253,0 4096 2 /

test1 7897 chenming rtd DIR 253,0 4096 2 /

test1 7897 chenming txt REG 253,0 8355 142202 /home/chenming/test1

test1 7897 chenming mem REG 253,0 1906308 38865 /lib/libc-2.12.so

test1 7897 chenming mem REG 253,0 122232 52742 /lib/libgcc_s-4.4.7-20120601.so.1

test1 7897 chenming mem REG 253,0 142600 38788 /lib/ld-2.12.so

test1 7897 chenming mem REG 253,0 202040 47921 /lib/libm-2.12.so

test1 7897 chenming mem REG 253,0 942040 52866 /usr/lib/libstdc++.so.6.0.13

test1 7897 chenming 0u CHR 1,3 0t0 3903 /dev/null

test1 7897 chenming 1u CHR 1,3 0t0 3903 /dev/null

test1 7897 chenming 2u CHR 1,3 0t0 3903 /dev/null

man 3 daemon可以查看到函数签名:

include

也可以自己实现一个:

include

include

include

include

include

include

redis里的实现要简单一些(redis.c):

void daemonize(void) {

int fd;

if (fork() != 0) exit(0); /* parent exits */
setsid(); /* create a new session */

/* Every output goes to /dev/null. If Redis is daemonized but
 * the ‘logfile‘ is set to ‘stdout‘ in the configuration file
 * it will not log at all. */
if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
    dup2(fd, STDIN_FILENO);
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);
    if (fd > STDERR_FILENO) close(fd);
}

}

memcached里的实现(daemon.c):

include

include

include

include

include “memcached.h”

int daemonize(int nochdir, int noclose)

{

int fd;

switch (fork()) {
case -1:
    return (-1);
case 0:
    break;
default:
    _exit(EXIT_SUCCESS);
}

if (setsid() == -1)
    return (-1);

if (nochdir == 0) {
    if(chdir("/") != 0) {
        perror("chdir");
        return (-1);
    }
}

if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
    if(dup2(fd, STDIN_FILENO) < 0) {
        perror("dup2 stdin");
        return (-1);
    }
    if(dup2(fd, STDOUT_FILENO) < 0) {
        perror("dup2 stdout");
        return (-1);
    }
    if(dup2(fd, STDERR_FILENO) < 0) {
        perror("dup2 stderr");
        return (-1);
    }

    if (fd > STDERR_FILENO) {
        if(close(fd) < 0) {
            perror("close");
            return (-1);
        }
    }
}
return (0);

}

“`

时间: 2024-10-08 10:34:20

Linux daemon进程原理与使用的相关文章

Linux daemon进程的应用、实现和原理

什么情况下用daemon进程 生产环境下,除了我们ssh登录上去,然后手动跑的那部分以外,其他都是自动运行的,这些大部分都应该是后台执行的.如何才能后台执行呢? nohup ./XXX & 由系统的其他daemon进程启动.这样的话,你的程序是它的子进程,跟终端没关系.退出终端也不会导致进程退出.如写在crontab里. 写成daemon程序,可以手动执行,退出终端时程序不退出. 如何选择呢? (1)首先,清理过期日志这一类需求,可以写一个死循环一直运行,也可以写在crontab里,每次执行完就

linux获取daemon进程的控制台数据

linux提供了一个daemon函数,使得进程可以脱离控制台运行,实现了后台运行的效果.但是进程后台运行后,原本在终端控制台输出的数据就看不到了.那么,怎样才能找回这些数据? 这里,文章主题就围绕着 如何获得后台进程的控制台数据,其中的原理要从daemon说起. daemon主要做两件事: 1.创建子进程,退出当前进程,并且以子进程创建新会话.这样,就算父进程退出,子进程也不会被关闭 2.将标准输入,标准输出,标准错误都重定向/dev/null daemon 实现大致如下: int daemon

Linux 守护进程的原理与实现

一.守护进程概述 在linux或者unix操作系统中在系统的引导的时候会开启很多服务,这些服务就叫做守护进 程.为了增加灵活性,root可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别以一定的方式配置系统. 守护进程是脱离于终端并且在后台运行的进程.守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端 信息所打断. 二.守护进程简介 守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长 的进程,通

.NET跨平台实践:用C#开发Linux守护进程-Daemon

Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为Linux开发与控制台无关的,需要在后台长时间不间断运行的“服务程序”,Daemon技术是非常重要的. Daemon程序一般用c/c++开发.不过,我今天要讲的,不是怎么用c/c++开发daemon,而是用C#! 一,创建Daemon程序: 用VS新建一个控制台项目,假设名称是MyDaemon,输入下

linux系统监控工具dstat、glances及实时进程查看工具htop(含部分进程原理)

简单罗列基础命令,只分享我的想法! 基于LinuxKernel是多人多任务的OS,Windows NT Kernel是单人多任务的OS,OS Kernel的功能无外乎是"承上启下"即驱动硬件.为上层应用程序提供系统调用.内存管理.FS管理.进程管理等,所以Linux的进程.线程机制和Windows有一些区别,我说的是原理. 当然了二进制程序文件肯定是有区别,因为进程就是程序向内核申请,由内核"审批"通过之后才能成为进程. Kernel的作用就是管理进程,所以,当程序

Linux系统编程——Daemon进程

目录 Daemon进程介绍 前提知识 Daemon进程的编程规则 Daemon进程介绍 Daemon运行在后台也称作"后台服务进程". 它是没有控制终端与之相连的进程.它独立与控制终端.会话周期的执行某种任务. 那么为什么守护进程要脱离终端后台运行呢? 守护进程脱离终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的任何终端信息所打断. 那么为什么要引入守护进程呢? 由于在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程

Linux超级守护进程——xinetd

一 Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程来执行的.守护进程是生存期长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.他们常常在系统引导装入时启动,在系统关闭时终止.linux系统有很多守护进程,大多数服务器都是用守护进程实现的.同时,守护进程完成许多系统任务,比如,作 业规划进程crond.打印进程lqd等.有些书籍

Linux守护进程详解(init.d和xinetd)

一 Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程来执行的.守护进程是生存期长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.他们常常在系统引导装入时启动,在系统关闭时终止.linux系统有很多守护进程,大多数服务器都是用守护进程实现的.同时,守护进程完成许多系统任务,比如,作 业规划进程crond.打印进程lqd等.有些书籍

Linux守护进程(init.d和xinetd)

一 Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台 的守护进程来执行的.守护进程是生存期长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.他们常常在系统引导装入时启 动,在系统关闭时终止.linux系统有很多守护进程,大多数服务器都是用守护进程实现的.同时,守护进程完成许多系统任务,比如,作 业规划进程crond.打印进程lqd等.有些