He,YuanHui —— 业精于勤荒于嬉,行成于思毁于随

如果你喜欢一个事,又有这样的才干,那就把整个人都投入进去,就要象一把刀直扎下去直到刀柄一样,不要问为什么,也不要管会碰到什么。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  240 随笔 :: 1 文章 :: 135 评论 :: 2 引用

公告

=========================================================

本文为转载,转载必须确保本文完整并完整保留原作者信息和本文链接

E-mail: khler@163.com

QQ:     23381103

MSN:   pragmac@hotmail.com

原文:

申明:转载只为传播知识,让更多人享受作者智慧的结晶!

如原作者对转载于此有异议,请立即联系本人,本人将在第一时间删除,并深表歉意!

=========================================================

 

 

LINUX Daemon程序设计

刘爱贵

Aigui.LIU@ihep.ac.cn

2006-11-2

引言

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 (&current_time);            /* Get current time */

        tm = localtime (&current_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源代码 http://castor.web.cern.ch/castor/

[3] 若干网络文献

posted on 2011-01-30 17:31 He,YuanHui 阅读(...) 评论(...) 编辑 收藏

Add to Google