写Daemon程序框架

什么是Daemon:
一个Daemon(或服务)是一个被设计成自动运行的后台进程,它很少或者根本就不需要用户干预。Apache服务http daemon就是这样的一个例子。他在后台等待监听某个端口,根据请求的类型,为页面或者脚本服务。
在Linux下建立一个daemon,需要以一个特定顺序使用一系列规则.了解它们如何工作,将帮助你理解daemon如何在Linux用户空间操作,也能调用内核操作。实际上,一些有内核模块的daemon接口能够同硬件设备工作,如外部控制板打印机,PDA等.

Deamon通信:
Daemon不应该直接通过终端同用户通信。实际上,daemon根本就不应该直接同用户通信。所有的通信都应该传给某些类型的接口。

基本的Daemon结构:
一个Daemon启动时,它必须做一些底层的家务,来准备实际的工作。这包括几个步骤:
1)从父进程分离
2)改变文件模式掩码(umask)
3)打开log文件,准备写入
4)建立一个唯一的会话ID(SID)
5)改变当前的工作目录到一个安全的地方
6)关闭标准的文件描述符
7)进入实际的daemon代码
1从父进程分离:
一个daemon可能被系统启动,也可能被用户终端启动,或者被脚本启动。当他启动时,跟系统中的其他可执行程序没什么分别。为了让它自治,实际的代码必须在一个子进程里执行。这就是众所周知的forking
注意调用fork之后的错误检查。写daemon时,你将必须做尽可能多的防御。实际上,一个daemon程序有较多的代码就是做错误检查的。fork()程序返回子进程的ID(pid,不等于0),如果失败则返回-1. 如果daemon不能开启新的进程,就要终止。
如果子进程成功创建,父进程也是一言不发就退出了。这似乎很奇怪,其实真正要做的事情,交给子进程去做了。

2 改变文件模式掩码(umask):
为了写任何由daemon创建的文件(包括logs), umask必须被改变以确认它们能被合适的写入或者读出。这跟在命令行改变它们类似,只不过我们这里是用程序实现的。
通过设置uamsk为0,我们将对daemon创建的文件有完全的权限。即使你不打算使用任何文件,设置umask也是一个好注意,因为这样你可以访问文件系统中的任何文件。

3 打开一个log文件准备写入:
这部分是可选的。但推荐你打开一个log文件。这可能是你唯一能查看调试信息的地方

4 建立一个唯一的Session ID(SID):
从这里,子进程必须从内核取得一个唯一的SID。否则,子进程将成为一个孤儿。
setsid()函数同fork()函数的返回类型一样。我们用类似的错误检查代码来检查是否建立了SID。

5 改变工作目录:
当前的工作目录必须被改到一个一定会存在的目录。因为许多Linux发行版病不完全遵循Linux文件结构标准,有个目录是一定存在的,那就是root. 
你再一次看到错误防护代码。chdir失败返回-1,在改变到root目录后,必须检查一次。

6 关闭标准的文件描述符号:

代码示例:

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

int main(void) {

    pid_t pid, sid;   /* Our process ID and Session ID */

    /* Fork off the parent process */
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }

    /* If we got a good PID, then we can exit the parent process. */
    if (pid > 0) {
        exit(EXIT_SUCCESS);
    }

    /* Change the file mode mask */
    umask(0);

    /* Open any logs here */ 
    ***************
    /* Create a new SID for the child process */
    sid = setsid();
    if (sid < 0) {
        exit(EXIT_FAILURE); /* Log the failure */
    }

    /* Change the current working directory */
    if ((chdir("/")) < 0) {
        exit(EXIT_FAILURE); /* Log the failure */
    }

    /* Close out the standard file descriptors */
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    /* Daemon-specific initialization goes here */

    /* The Big Loop */
    while (1) {
        /* Do some task here ... */
        sleep(30); /* wait 30 seconds */
    }

    exit(EXIT_SUCCESS);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值