[1]
http://www.google.com.hk/search?hl=en&safe=active&q=linux+daemon%E7%94%A8%E6%88%B7&aq=f&aqi=&aql=&oq=
[2]
http://hi.baidu.com/bingqingwu5799/blog/item/5efba486914cdb26c65cc357.html
Linux Daemon 介绍(1)
2010-05-30 17:17本文出自 “zxuhong” 博客,请务必保留此出处http://zxuhong.blog.51cto.com/368977/99283
Linux 守护进程
Linux 守护进程概述
Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。
守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。
一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。
工作原理
Linux 守护进程的工作模式是服务器/客户机(Server/Client),服务器在一个特定的端口上监听(Listen)等待客户连接,连接成功后服务器和客户端通过端口进行数据通信。守护进程的工作就是打开一个端口,并且监听(Listen)等待客户连接。如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听其他的服务请求。
工作模式
Linux 守护进程有两种工作模式:stand-alone模式和xinetd模式。
(1)stand-alone模式
独立运行的守护进程由init负责管理,所有独立运行守护进程的脚本在/etc/rc.d/init.d/目录下。独立运行的守护进程工作方式称作stand-alone,是Unix传统的C/S模式的访问模式。服务器监听(Listen)在一个特点的端口上等待客户端的联机。如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听。工作在stand-alone模式下的网络服务有route、gated、web服务器等。在Linux系统中通过stand-alone工作模式启动的服务由/etc/rc.d/下面对应的运行级别当中的符号链接启动。
(2)xinetd模式
从守护进程的概念可以看出,对于系统所要求的每一种服务,都必须运行一个监听某个端口连接所发生的守护进程,这意味着资源浪费。为了解决这个问题,Linux引进了"网络守护进程服务程序"的概念。Redhat Linux使用的网络守护进程是xinted(eXtended InterNET Daemon)。和stand-alone模式相比xinetd模式也称 Internet Super-Server(超级服务器)。xinetd能够同时监听多个指定的端口,在接受用户请求时,他能够根据用户请求的端口不同,启动不同的网络服务进程来处理这些用户请求。可以把xinetd看做一个管理启动服务的管理服务器,它决定把一个客户请求交给那个程序处理,然后启动相应的守护进程。
和stand-alone工作模式相比,系统不必为每一个网络服务进程监听其服务端口,运行xinetd守护进程就可以同时监听所有服务端口,这样就降低了系统开销,保护系统资源。但是对于访问量大、经常出现并发访问时,xinetd想要频繁启动对应的网络服务进程,反而会导致系统性能下降。一般来说系统一些负载高的服务,比如Apache、sendmail等服务是单独启动的。而其他服务类型都可以使用xinetd超级服务器管理。
查看系统为Linux服务提供那种模式方法在Linux命令行可以使用pstree命令可以看到两种不同方式启动的网络服务。
Linux 守护进程管理
Linux提供了几种不同的守护进程管理工具: ntsysv、chkconfig等,可以根据具体需要灵活运用。
(1)ntsysv
ntsysv 工具为启动或关闭由xinetd管理的服务提供了简单的界面,也可以使用 ntsysv 来配置运行级别。按照默认设置,只有当前运行级别会被配置。要配置不同的运行级别,使用 --level 选项来指定一个或多个运行级别。比如,命令 ntsysv --level 345 配置运行级别3、4、和5。使用上下箭头来上下查看列表。使用空格键来选择或取消选择服务,或用来"按"「确定」和「取消」按钮。要在服务列表和「确定」、「取消」按钮中切换,使用 [Tab]键。* 标明某服务被设为启动。[F1] 键会弹出每项服务的简短描述。
(3)chkconfig
Chkconfig工具可以用来启动或停止服务。
chkconfig --list 命令显示系统服务列表,以及这些服务在运行级别0到6中已被启动(on)还是停止(off),还显示xinetd管理的系统服务。
chkconfig 还能用来设置某一服务在某一指定的运行级别内被启动还是被停运。比如,要在运行级别3、4、5中停运 nfs 服务,使用下面的命令: chkconfig --level 345 nfs off
查看系统为Linux服务提供那种模式方法在Linux命令行可以使用pstree命令可以看到两种不同方式启动的网络服务。
[3]
http://blog.csdn.net/ast_224/archive/2009/02/03/3860680.aspx
Daemon程序简介
Daemon是长时间运行的进程,通常在系统启动后就运行,在系统关闭时才结束。一般说Daemon程序在后台运行,是因为它没有控制终端,无法和前台的用户交互。Daemon程序一般都作为服务程序使用,等待客户端程序与它通信。我们也把运行的Daemon程序称作守护进程。
比如,我们的网络服务程序,可以在完成创建套接口,绑定套接口,设置套接口为监听模式后,变成守护进程进入后台执行而不占用控制终端,这是网络服务程序的常用模式。UNIX下的网络服务程序,如Web Server,FTP,Telnet一般都是由守护进程(Daemon)来实现的。守护进程不占用终端,在后台运行。UNIX的守护进程一般都命名为 *d 的形式,如httpd,telnetd等等。
守护进程一旦脱离了终端,退出就成了问题。使用 ps axj 查出进程ID然后 kill ID 之。
Daemon程序编写规则
编写Daemon程序有一些基本的规则,以避免不必要的麻烦。
1、首先是程序运行后调用fork,并让父进程退出。子进程获得一个新的进程ID,但继承了父进程的进程组ID。
2、调用setsid创建一个新的session,使自己成为新session和新进程组的leader,并使进程没有控制终端(tty)。
3、改变当前工作目录至根目录,以免影响可加载文件系统。或者也可以改变到某些特定的目录。
4、设置文件创建mask为0,避免创建文件时权限的影响。
5、关闭不需要的打开文件描述符。因为Daemon程序在后台执行,不需要于终端交互,通常就关闭STDIN、STDOUT和STDERR。其它根据实际情况处理。另一个问题是Daemon程序不能和终端交互,也就无法使用printf方法输出信息了。
另一个问题是Daemon程序不能和终端交互,也就无法使用printf方法输出信息了。我们可以使用syslog机制来实现信息的输出,方便程序的调试。
下面是一个daemon程序的例子:(daemontest.c)
view plaincopy to clipboardprint?
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <syslog.h>
#include <signal.h>
int daemon_init(void)
{
pid_t pid;
if((pid = fork()) < 0)
return(-1);
else if(pid != 0)
exit(0); /* parent exit */
/* child continues */
setsid(); /* become session leader */
chdir("/"); /* change working directory */
umask(0); /* clear file mode creation mask */
close(0); /* close stdin */
close(1); /* close stdout */
close(2); /* close stderr */
return(0);
}
void sig_term(int signo)
{
if(signo == SIGTERM)
/* catched signal sent by kill(1) command */
{
syslog(LOG_INFO, "program terminated.");
closelog();
exit(0);
}
}
int main(void)
{
if(daemon_init() == -1)
{
printf("can\'t fork self\n");
exit(0);
}
openlog("daemontest", LOG_PID, LOG_USER);
syslog(LOG_INFO, "program started.");
signal(SIGTERM, sig_term); /* arrange to catch the signal */
while(1)
{
sleep(1); /* put your main program here */
}
return(0);
}
使用如下命令编译该程序: gcc -Wall -o daemontest daemontest.c编译完成后生成名为daemontest的可执行程序,执行./daemontest来测试程序的运行。
使用ps axj命令可以显示系统中已运行的daemon程序的信息,包括进程ID、session ID、控制终端等内容。部分显示内容:
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 17765 17765 17765 ? -1 Ss 0 0:00 ./daemontest
从中可以看到daemontest程序运行的进程号为17765。
我们再来看看/var/log/messages文件中的信息:
Feb 3 17:09:30 localhost daemontest[17765]: program started.
显示了我们在程序中希望输出的信息。
使用kill 17765命令来杀死这个进程,/var/log/messages文件中就会有如下的信息:
Feb 3 17:12:26 localhost daemontest[17765]: program terminated.
再使用ps axj命令检查,发现系统中daemontest进程已经没有了。
[4]
http://socol.javaeye.com/blog/518916
2009-11-17
怎么写Daemon程序
关键字: how to daemon
引用自:
http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html
http://www.qqgb.com/Netware/Linux/Linux7/82888.html
作者:Devin Watson
译者:Li Zhiwei
第一版 2004年5月
本文讲述如何用GCC在Linux编写Daemon. 使用本文档需要Linux和C方面的知识。原文版权属于Devin Watson,以BSD许可发布. (翻译时略有删节)
1.介绍:什么是Daemon
一个Daemon(或服务)是一个被设计成自动运行的后台进程,它很少或者根本就不需要用户干预。Apache服务http daemon就是这样的一个例子。他在后台等待监听某个端口,根据请求的类型,为页面或者脚本服务。
在Linux下建立一个daemon,需要以一个特定顺序使用一系列规则.了解它们如何工作,将帮助你理解daemon如何在Linux用户空间操作,也能调用内核操作。实际上,一些有内核模块的daemon接口能够同硬件设备工作,如外部控制板打印机,PDA等.
2.1 它要做什么
一个Daemon程序应该只做一件事情,并要做好。这件事情可能是像管理在多个域名上的数以百计的邮箱这么复杂的事情,也可能是 写一个报告,调用sendmail发送给管理员这么简单。
不管怎样,你应该有一个好的计划。如果它同其他daemon有互操作,这也是考虑好的事情.
2.2 如何互动
Daemon不应该直接通过终端同用户通信。实际上,daemon根本就不应该直接同用户通信。所有的通信都应该传给某些类型的接口(可能是你写的,或者你不必写这样一个接口),它可能是复杂的GTK+ GUI,也可能是简单的signal
3.基本的Daemon结构
一个Daemon启动时,它必须做一些底层的家务,来准备实际的工作。这包括几个步骤:
1)从父进程分离
2)改变文件模式掩码(umask)
3)打开log文件,准备写入
4)建立一个唯一的会话ID(SID)
5)改变当前的工作目录到一个安全的地方
6)关闭标准的文件描述符
7)进入实际的daemon代码
3.1从父进程分离
一个daemon可能被系统启动,也可能被用户终端启动,或者被脚本启动。当他启动时,跟系统中的其他可执行程序没什么分别。为了让它自治,实际的代码必须在一个子进程里执行。这就是众所周知的forking
注意调用fork之后的错误检查。写daemon时,你将必须做尽可能多的防御。实际上,一个daemon程序有较多的代码就是做错误检查的。fork()程序返回子进程的ID(pid,不等于0),如果失败则返回-1. 如果daemon不能开启新的进程,就要终止。
如果子进程成功创建,父进程也是一言不发就退出了。这似乎很奇怪,其实真正要做的事情,交给子进程去做了。
3.2 改变文件模式掩码(umask)
为了写任何由daemon创建的文件(包括logs), umask必须被改变以确认它们能被合适的写入或者读出。这跟在命令行改变它们类似,只不过我们这里是用程序实现的。
通过设置uamsk为0,我们将对daemon创建的文件有完全的权限。即使你不打算使用任何文件,设置umask也是一个好注意,因为这样你可以访问文件系统中的任何文件。
3.3 打开一个log文件准备写入
这部分是可选的。但推荐你打开一个log文件。这可能是你唯一能查看调试信息的地方。
3.4 建立一个唯一的Session ID(SID)
从这里,子进程必须从内核取得一个唯一的SID。否则,子进程将成为一个孤儿。
setsid()函数同fork()函数的返回类型一样。我们用类似的错误检查代码来检查是否建立了SID
3.5 改变工作目录
当前的工作目录必须被改到一个一定会存在的目录。因为许多Linux发行版病不完全遵循Linux文件结构标准,有个目录是一定存在的,那就是root.
你再一次看到错误防护代码。chdir失败返回-1,在改变到root目录后,必须检查一次。
3.6 关闭标准的文件描述符号
代码示例:
C代码
#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) {
/* Our process ID and Session ID */
pid_t pid, sid;
/* 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) {
/* Log the failure */
exit(EXIT_FAILURE);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
/* Log the failure */
exit(EXIT_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);
}
[5]