守护进程:在后台运行,不受终端控制
#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;
/* Clear file creation mask
防止文件模式可能会被设置为拒绝某些权限 */
umask(0);
/* Get maximum number of file descriptors */
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) /* parent */
exit(0);
//创建新会话:(1)成为新会话的收进程 (2)成为一个新进程组的组长进程 (3)脱离控制终端
setsid();
//忽略SIGHUP信号
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) /* parent */
exit(0);
if(chdir("/") < 0) // 当前目录更改为工作目录
err_quit("%s: can't change directory to /", cmd);
/* Close all open file descriptors */
if(rl.rlim_max == RLIM_INFINITY)
rl.rlim_max = 1024;
for(i=0; i<rl.rlim_max; i++)
close(i);
/* Attach file descriptors 0, 1, 2 to /dev/null */
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
/* Initialize the log file */
/*
void openlog(const char *ident, int option, int facility);
ident:程序名称。
option:指定许多项的位屏蔽。
LOG_CONS---若日志消息不能通过UNIX域数据报送至syslogd,
则将该消息写至控制台。
facility:目的是可以让配置文件说明,来自不同设施的消息将以不同方式进行处理。
LOG_DAEMON---系统守护进程。
*/
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);
}
}
int main(void)
{
daemonize("cron");
定义函数执行cron操作
}