Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1252044
  • 博文数量: 247
  • 博客积分: 5587
  • 博客等级: 大校
  • 技术积分: 2060
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-24 13:27
文章分类
文章存档

2012年(101)

2011年(44)

2010年(102)

分类: LINUX

2010-07-03 10:55:17

引言

Daemon程序,又称为守护进程,通常在系统后台长时间运行,由于没有控制终端而无法与前台交互。Daemon程序一般作为系统服务使用,Linux系统中运行着很多这样的守护进程,如iptablesnfsypbinddhcpd等。

Daemon设计原则

Daemon程序设计主要原则包括:

(1)       程序运行后调用fork,并让父进程退出。子进程获得一个新的进程ID,但继承了父进程的进程组ID

(2)       调用setsid创建一个新的session,使自己成为新session和新进程组的leader,并使进程没有控制终端(tty)

(3)       设置文件创建mask0,避免创建文件时权限的影响。

(4)       关闭不需要的打开文件描述符。因为Daemon程序在后台执行,不需要于终端交互,通常就关闭STDINSTDOUTSTDERR。其它根据实际情况处理。

(5)       Daemon无法输出信息,可以使用SYSLOG或自己的日志系统进行日志处理。(可选)

(6)       编写管理DaemonSHELL脚本,使用serviceDaemon进行管理和监控。(可选)

Daemon程序框架

int init_daemon(void)

{

  pid_t pid;

  int i;

 

  /* parent exits , child continues */

  if((pid = fork()) < 0)

    return -1;

  else if(pid != 0)

    exit(0);

 

  setsid(); /* become session leader */

 

  for(i=0;i< NOFILE ;++i) /* close STDOUT, STDIN, STDERR, */

    close(i);

 

  umask(0); /* clear file mode creation mask */

  return 0;

}

 

void sig_term(int signo)

{

  if(signo == SIGTERM)  /* catched signal sent by kill(1) command */

  {

     wsio_logit("", "wsiod stopped\n");

     exit(0);

 }

}

 

/* main program of daemon */

int main(void)

{

if(init_daemon() == -1){

printf("can't fork self\n");

exit(0);

  }

  wsio_logit("", "wsiod started\n");

  signal(SIGTERM, sig_term); /* arrange to catch the signal */

 

  while (1) {

    // Do what you want here

    … …

  }

  exit(0);

}

Daemon日志

这里使用自己的日志系统,当然也可以使用SYSLOG

#define LOGBUFSZ 256     /*log buffer size*/

#define LOGFILE  "/var/log/wsiod.log"  /*log filename*/

int wsio_logit(char * func, char *msg, ...)

{

        va_list args;

        char prtbuf[LOGBUFSZ];

        int save_errno;

        struct tm *tm;

        time_t current_time;

        int fd_log;

 

        save_errno = errno;

        va_start (args, msg);

        (void) time (¤t_time);            /* Get current time */

        tm = localtime (¤t_time);

        sprintf (prtbuf, "%02d/%02d %02d:%02d:%02d %s ", tm->tm_mon+1,

                    tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, func);

        vsprintf (prtbuf+strlen(prtbuf), msg, args);

        va_end (args);

        fd_log = open (LOGFILE, O_WRONLY | O_CREAT | O_APPEND, 0664);

        write (fd_log, prtbuf, strlen(prtbuf));

        close (fd_log);

        errno = save_errno;

        return 0;

}

Daemon管理

Daemon程序可以使用service工具进行管理,包括启动、停止、查看状态等,但前题是需要编写一个如下的简单SHELL脚本。

# /etc/rc.d/init.d/wsiod

#!/bin/sh

#

# wsiod         This shell script takes care of starting and stopping wsiod.

#

# chkconfig: 35 65 35

# description: wsiod is web servce I/O server, which is used to access files on remote hosts.

 

# Source function library.

. /etc/rc.d/init.d/functions

 

# Source networking configuration.

. /etc/sysconfig/network

 

# Check that networking is up.

[ ${NETWORKING} = "no" ] && exit 0

 

RETVAL=0

prog="wsiod"

WSIOARGS="-h $HOSTNAME -p 80 -t STANDALONE -k -c -d"

start() {

        # Start daemons.

        echo -n $"Starting $prog: "

        daemon /usr/local/bin/wsiod ${WSIOARGS}

        RETVAL=$?

        echo

        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/wsiod

        return $RETVAL

}

stop() {

        # Stop daemons.

        echo -n $"Shutting down $prog: "

        killproc wsiod

        RETVAL=$?

        echo

        [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/wsiod

        return $RETVAL

}

 

# See how we were called.

case "$1" in

  start)

        start

        ;;

  stop)

        stop

        ;;

  restart|reload)

        stop

        start

        RETVAL=$?

        ;;

  status)

        status wsiod

        RETVAL=$?

        ;;

  *)

        echo $"Usage: $0 {start|stop|restart|status}"

        exit 1

esac

 

exit $RETVAL

 

OK,到这儿为止,一个完整的Linux Daemon程序就完成了。

参考文献

[1] Linux C高级程序员指南/毛曙福编著,北京,国防工业出版社,2001.2

[2] CASTOR NS源代码

[3] 若干网络文献

阅读(1938) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~