=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 void err_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. */ void err_quit( const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit( 0 , 0 , fmt, ap); va_end(ap); exit( 1 ); } int lockfile( 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)); } int already_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 ); } void daemonize( 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