=Start=
缘由:
以后估计会经常和daemon进程打交道,所以在这里整理一下Linux的C语言中daemon进程编写的函数,方便以后直接使用。
正文:
参考解答:
#include <unistd.h>#include <stdlib.h>#include <fcntl.h>#include <syslog.h>#include <string.h>#include <stdio.h>#include <sys/stat.h>#include <sys/resource.h>#include <errno.h> /* for definition of errno */#include <stdarg.h> /* ISO C variable aruments */#define LOCKFILE "/var/run/daemon.pid"#define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)#define MAXLINE 4096 /* max line length *//* * Print a message and return to caller. * Caller specifies "errnoflag". */static voiderr_doit(int errnoflag, int error, const char *fmt, va_list ap){ char buf[MAXLINE]; vsnprintf(buf, MAXLINE, fmt, ap); if (errnoflag) snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s", strerror(error)); strcat(buf, "\n"); fflush(stdout); /* in case stdout and stderr are the same */ fputs(buf, stderr); fflush(NULL); /* flushes all stdio output streams */}/* * Fatal error unrelated to a system call. * Print a message and terminate. */voiderr_quit(const char *fmt, ...){ va_list ap; va_start(ap, fmt); err_doit(0, 0, fmt, ap); va_end(ap); exit(1);}intlockfile(int fd){ struct flock fl; fl.l_type = F_WRLCK; fl.l_start = 0; fl.l_whence = SEEK_SET; fl.l_len = 0; return(fcntl(fd, F_SETLK, &fl));}intalready_running(void){ int fd; char buf[16]; fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE); if (fd < 0) { syslog(LOG_ERR, "can't open %s: %s", LOCKFILE, strerror(errno)); exit(1); } if (lockfile(fd) < 0) { if (errno == EACCES || errno == EAGAIN) { close(fd); return(1); } syslog(LOG_ERR, "can't lock %s: %s", LOCKFILE, strerror(errno)); exit(1); } ftruncate(fd, 0); sprintf(buf, "%ld", (long)getpid()); write(fd, buf, strlen(buf)+1); return(0);}voiddaemonize(const char *cmd){ int i, fd0, fd1, fd2; pid_t pid; struct rlimit rl; /* * Initialize the log file. */ openlog(cmd, LOG_CONS, LOG_DAEMON); /* * Clear file creation mask. */ umask(0); /* * Get maximum number of file descriptors. */ if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { syslog(LOG_ERR, "%s: can't get file limit", cmd); exit(1); } /* * Become a session leader to lose controlling TTY. */ if ((pid = fork()) < 0) { syslog(LOG_ERR, "%s: can't fork", cmd); exit(1); } else if (pid != 0) /* parent */ exit(0); setsid(); /* * Ensure future opens won't allocate controlling TTYs. */ if ((pid = fork()) < 0){ syslog(LOG_ERR, "%s: can't fork", cmd); exit(1); } else if (pid != 0) /* parent */ exit(0); /* * Change the current working directory to the root so * we won't prevent file systems from being unmounted. */ if (chdir("/") < 0) { syslog(LOG_ERR, "%s: can't change directory to /", cmd); exit(1); } /* * 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, and 2 to /dev/null. */ fd0 = open("/dev/null", O_RDWR); fd1 = dup(0); fd2 = dup(0); if (fd0 != 0 || fd1 != 1 || fd2 != 2) { syslog(LOG_ERR, "%s: unexpected file descriptors %d %d %d", cmd, fd0, fd1, fd2); exit(1); }}int main(int argc, char *argv[]){ char *cmd; if ((cmd = strrchr(argv[0], '/')) == NULL) cmd = argv[0]; else cmd++; /* * Become a daemon. */ daemonize(cmd); /* * Make sure only one copy of the daemon is running. */ if (already_running()) { syslog(LOG_ERR, "daemon already running"); exit(1); } /* * code here */ return 0;} |
参考链接:
http://man7.org/linux/man-pages/man3/daemon.3.html
https://stackoverflow.com/questions/17954432/creating-a-daemon-in-linux
http://alfred-sun.github.io/blog/2015/06/18/daemon-implementation/
https://typecodes.com/cseries/apuesingledaemonprocess.html
http://debugo.com/apue-deamon/
https://notes.shichao.io/apue/ch13/ #里面有几张很棒的图
=END=
《 “LINUX下守护进程的C语言实现#2” 》 有 2 条评论
PHP实现daemon
https://liaoaoyang.cn/articles/2017/08/22/php-daemon/
在PHP中生成守护进程(Daemon Process)
http://bayescafe.com/php/create-daemon-process-with-php.html
如何使用PHP编写daemon process
http://blog.codinglabs.org/articles/write-daemon-with-php.html
https://stackoverflow.com/questions/881388/what-is-the-reason-for-performing-a-double-fork-when-creating-a-daemon