Advanced Programming in UNIX environment: single-instance daemon implementation

Source: Internet
Author: User
Tags openlog

The book "Advanced Programming in UNIX environments" comes with many small and exquisite programs. When I read this book, rewrite the code in the book according to your own understanding (most of them are on the copybook) to deepen your understanding (it's too difficult to read a book, huh, huh ). This example is successfully tested on ubuntu10.04.


Program Introduction: This demo is a single-instance daemon implemented according to the programming rules of the Unix daemon.


// Apue program 13-1: initialize a daemon process // apue program 13-2: ensure that only one copy of a daemon is running // apue Program 14-5: Lock the entire file # include <stdio. h> # include <stdlib. h> # include <string. h> # include <unistd. h> # include <fcntl. h> # include <time. h> # include <signal. h> # include <errno. h> # include <sys/resource. h> # include <sys/syslog. h> # include <sys/file. h> # include <sys/STAT. h> // the path for creating the lock file # define lockfile "/var/run/daemon. PID "// lock file opening mode # define lockmode (s_irusr | S _ Iwusr | s_irgrp | s_iroth) // output the error message and exit void error_quit (const char * Str) {fprintf (stderr, "% s \ n", STR ); exit (1);} // Add the record lock int lockfile (int fd) {struct flock FL; FL. l_type = f_wrlck; FL. rochelle start = 0; FL. rochelle whence = seek_set; FL. rochelle Len = 0; return fcntl (FD, f_setlk, & FL) ;}// if the program is already running, 1 is returned; otherwise, 0int already_running (void) {int FD; char Buf [16]; // open the file FD = open (lockfile, o_rdwr | o_creat, lockmode); If (FD <0) {syslog (log_err, "can't open % s: % s", lockfile, strerror (errno); exit (1 );} // try to lock the file FD. // If the lock fails, if (lockfile (FD) <0) {// if the permission is insufficient or the resource is temporarily unavailable, 1if (eacces = errno | eagain = errno) {close (FD); return 1 ;}// otherwise, an error occurs in the program, log out of syslog (log_err, "can't lock % s: % s", lockfile, strerror (errno); exit (1 );} // first clear the file FD, and then write the current process number ftruncate (FD, 0) to it; sprintf (BUF, "% lD", (long) getpid (); write (FD, Buf, strle N (BUF) + 1); Return 0;} // change a process to daemonize (void) {int I, fd0, fd1, fd2; pid_t PID; struct rlimit RL; struct sigaction SA; // see annotation 1 umask (0); // obtain the maximum file description number int temp; temp = getrlimit (rlimit_nofile, & RL ); if (temp <0) error_quit ("can't get file limit"); // See note 2, pid = fork (); If (PID <0) error_quit ("can't fork"); else if (PID! = 0) Exit (0); // See note 3 setsid (); SA. sa_handler = sig_ign; sigemptyset (& SA. sa_mask); SA. sa_flags = 0; temp = sigaction (sighup, & SA, null); If (temp <0) error_quit ("can't ignore sighup "); /// ensure that the sub-process does not have the opportunity to be assigned to a control terminal pid = fork (); If (PID <0) error_quit ("can't fork "); else if (PID! = 0) Exit (0); // See note 4 temp = chdir ("/"); If (temp <0) error_quit ("can't change directoy to/"); // see the 5if (RL. rlim_max = rlim_infinity) RL. rlim_max = 1024; for (I = 0; I <RL. rlim_max; I ++) Close (I); // See note 6fd0 = open ("/dev/null", o_rdwr); fd1 = DUP (0 ); fd2 = DUP (0); If (fd0! = 0 | fd1! = 1 | fd2! = 2) {syslog (log_err, "unexpected file descriptors % d", fd0, fd1, fd2); exit (1 );}} // This main function is my original, heap int main (void) {// open the System Log File openlog ("My test log:", log_cons, log_daemon ); daemonize (); // if the program is already running, write a sentence to the record file, and then exit if (already_running () {syslog (log_err, "daemon alread running "); closelog (); return 1 ;}// start (current) Time of the program to write data to the log file. // After 100 seconds, the end time of writing data to the record file, then the program time_t TT = time (0); syslog (log_info, "the log program start at: % s", asctime (localtime (& TT ))); sleep (100); // pause () TT = time (0); syslog (log_info, "the log program end at: % s ", asctime (localtime (& TT); // close the log file // although it is none, write closelog () to match openlog (); return 0 ;}


Running example (in red ):

Qch @ Ubuntu :~ /Code $ GCC temp. C-o
Temp
Qch @ Ubuntu :~ /Code $ sudo./temp
Qch @ Ubuntu :~ /Code $ sudo./temp
Qch @ Ubuntu :~ /Code $ PS axj | grep temp
1 2648 2647 2647? -1 s 0: 00./temp
2127 2673 2672 2127 pts/0 2672 S + 1000 grep -- color = auto temp

# Open the log file two minutes later and check the program log
Qch @ Ubuntu :~ /Code $ tail-F/var/log/syslog
SEP 24 07:53:58 Ubuntu my test log: The log program start at: Mon Sep 24 07:53:58 2012
SEP 24 07:54:07 Ubuntu my test log: Daemon alread running
SEP 24 07:55:38 Ubuntu my test log: The log program end at: Mon Sep 24 07:55:38 2012

Annotation: programming rules for daemon
1: First, you must call umask to set the blocking character created in file mode to 0. Some permissions may be denied to create blocking characters in the inherited file mode.
2: Call fork and exit the parent process ). In this way, two points are implemented: First, if the daemon is started as a simple shell command, the termination of the parent process makes shell think that the command has been executed; second, the child process inherits the process group ID of the parent process, but has a new process ID, which ensures that the child process is not the leader process of the process group. This is a prerequisite for setsid calls.
3: Call setsid to create a new session. Perform three operations: (a) the first process of the new session, (B) the leader process of the new process, and (c) no control terminal.
4: change the current working directory to the root directory. When a process is active, the file system of its working directory cannot be detached. Generally, you need to change the working directory to the root directory. For processes that need to dump the core, write the running log to change the working directory to a specific directory.
5: disable unnecessary file descriptors. A process inherits the opened file descriptor from the parent process that created it. If you do not close it, system resources will be wasted, and the file system where the process is located will not be able to be detached and unexpected errors will occur.
6: Redirection 0, 1, 2 to/dev/null, so that any library that tries to read standard input, write standard output and standard error will not produce any effect.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.