一、概念
守护进程是生存期长的一种进程。它们常常在系统引导安装时启动,仅在系统关闭时才终止。因为它们没有控制终端,所以说它们是在后台运行的。Unix系统有很多守护进程,他们执行日常事务活动。
二、特征
1、在使用 ps 命令(例如:ps -axj)输出的信息中,进程名使用方括号标记。
2、进程ID为1的进程是系统守护进程init。
3、大多数守护进程都已超级用户root特权运行,这也是守护进程没有终端控制的原因。
4、守护进程有系统守护进程和用户层守护进程。
三、编写规则
1、首先调用 umask 将文件模式创建屏蔽字设置为一个已知值(通常为0)。
2、调用 fork ,然后使父进程 exit 。
3、调用 setsid 创建一个新回话,使调用进程成为 新回话的首进程、成为新进程的组长进程、没有控制终端。
4、将当前目录更改为根目录。
5、关闭不再需要的的文件描述符。
6、某些守护进程打开 /dev/null 使其具有文件描述符0、1、2,这样任何一个试图读标准输入、写标准输出或标准错误的库例程都不会产生任何效果。
/* *下面例子函数可供想要初始化为守护进程的程序调用 */ #include "apue.h" #include <syslog.h> #include <fcntl.h> #include <sys/resource.h> void daemonize( const char *cmd ) { int i, fd0, fd1, fd2; pid_t pid; struct rlimit rl; struct sigaction sa; umask(0); if( getrlimit(RLIMIT_NOFILE, &rl) < 0 ) err_quit("%s : can't get file limit ", cmd); if( ( pid = fork() ) < 0 ) err_quit("%s : can't fork ", cmd); else if( pid != 0 ) exit(0); setsid(); sa.sa_handler = SIG_IGN; sigemptyset( &sa.sa_mask ); sa.sa_flags = 0; if( sigaction(SIGHUP, &sa, NULL) < 0 ) err_quit(" %s: can't ignore SIGHUP ", cmd); if( ( pid = fork() ) < 0 ) err_quit("%s : can't fork ", cmd); else if( pid != 0 ) exit(0); if( chdir("/") < 0 ) err_quit(" %s: can't change directory to / ", cmd); if( rl.rlim_max == RLIM_INFINITY ) rl.rlim_max = 1024; for( i = 0; i < rl.rlim_max; i++ ) close(i); fd0 = open("/dev/null", O_RDWR); fd1 = dup(0); fd2 = dup(0); openlog( cmd, LOG_CONS, LOG_DAEMON); if( fd0 != 0 || fd1 != 1 || fd2 != 2 ){ syslog( LOG_ERR, "unexpected file descriptors %d %d %d", fd0, fd1, fd2); exit(1); } }
参考《UNIX环境高级编程第三版》