daemon

本文介绍两种创建守护进程的方法:手动实现和使用daemon函数。通过具体的C语言代码示例,展示了如何使进程脱离终端并运行在后台。此外还介绍了如何设置工作目录、文件权限掩码以及重定向标准输入、输出。

守护进程是一个很重要的概念,但本质上就是一个去除所有可知的依赖以保持独立的进程,说的再多不如动手来一遍。

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

void create_daemon_by_self(void)
{
    pid_t pid_t1;
    int ret = -1;
    long fd_max = -1;

    pid_t1 = fork();    //fork一个新进程
    if(pid_t1 < 0)
    {
        perror("fork");
        exit(0);
    }
    if(pid_t1 > 0)
    {
        printf("end parent process.\n");    //结束父进程
        exit(0);
    }
    pid_t1 = setsid();    //设置新的会话
    if(pid_t1 < 0)
    {
        perror("setsid");
        exit(0);
    }
    ret = chdir("/");     //设置工作目录
    if(ret < 0)
    {
        perror("chdir");
        exit(0);
    }
    umask(0);             //设置最大的文件操作权限
    fd_max = sysconf(_SC_OPEN_MAX);      //关闭所有的文件操作,一般关闭0,1,2就行了
    for(int i = 0; i < fd_max; i++)
    {
        close(i);
    }
    open("/dev/null", O_RDWR);          //把标准输入输出标准错误绑定到一个空设备
    dup(0);
    dup(0);
}

void create_daemon_by_daemon(void)
{
    int ret = -1;
    printf("Hi, create_daemon_by_daemon.\n");
    ret = daemon(0, 0);    //使用daemon接口创建守护进程,简单很多!!!!
    if (ret != 0)
        exit(0);
}

void do_something(void)
{
    openlog("hello", LOG_PID | LOG_CONS, LOG_USER);
    int count = 10;
    while(count--)
    {
        sleep(1);
        syslog(LOG_INFO, "hello world=%d", count);
    }
    closelog();
}

void do_exit(void)
{
    printf("Hi, I'm exit.\n");
}

int main(int argc, char const *argv[])
{
    atexit(do_exit);
    // create_daemon_by_self();
    create_daemon_by_daemon();
    do_something();
    return 0;
}


05-22
### Daemon 的概念 在计算领域,Daemon 是一种后台运行的服务程序,通常用于执行特定的任务或等待事件的发生。它独立于用户会话,在操作系统启动时自动加载并持续运行直到系统关闭[^1]。 Linux 和 Unix 系统中的 Daemons 负责处理各种任务,例如日志记录(syslogd)、打印作业管理(lpd),以及网络服务提供(sshd)。这些进程通常是无交互式的,并通过初始化脚本配置其行为。 #### 创建一个简单的 Daemon 进程 创建一个 Daemon 需要遵循一系列标准步骤来确保其能够脱离控制终端并在后台稳定工作: 1. **Fork 子进程** 主进程 fork 出子进程后退出,使子进程成为孤儿进程由 init 进程接管。 2. **设置会话 ID (setsid)** 使用 `setsid()` 将当前进程与任何现有会话分离,防止接收信号如挂起 (`SIGHUP`)。 3. **更改目录至根路径 (/)** 或指定的工作目录 此操作避免因某些文件系统的卸载而导致错误。 4. **重置文件模式掩码 (umask)** 设置 umask 值以确保生成的文件具有适当权限。 5. **重定向标准输入/输出流** 关闭默认的标准输入、输出和错误描述符并将它们重新指向 `/dev/null` 或其他合适位置。 下面是一个 Python 实现简单 Daemon 的例子: ```python import os import sys import time def create_daemon(): try: pid = os.fork() if pid > 0: # Parent process exits sys.exit(0) except OSError as e: print(f"Fork failed: {e}", file=sys.stderr) sys.exit(1) # Decouple from parent environment os.chdir("/") os.setsid() os.umask(0) with open('/dev/null', 'r') as dev_null_in, \ open('/dev/null', 'a+') as dev_null_out_err: os.dup2(dev_null_in.fileno(), sys.stdin.fileno()) os.dup2(dev_null_out_err.fileno(), sys.stdout.fileno()) os.dup2(dev_null_out_err.fileno(), sys.stderr.fileno()) if __name__ == "__main__": create_daemon() while True: with open("/tmp/daemon.log", "a") as log_file: log_file.write("Daemon running...\n") time.sleep(60) ``` 此代码片段展示了如何构建基本的守护进程框架,其中涉及的关键技术已在前面提到过。 #### 安全性和隔离机制 为了增强安全性,许多现代守护进程会在受限环境中运行,比如 chroot Jail。这种环境下,进程只能访问指定范围内的资源,从而减少潜在攻击面[^2]。管理员需定期审查此类环境的内容以防恶意软件突破限制。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值