In apue, why do I need to fork twice when creating a daemon?

Source: Internet
Author: User
1. General steps for creating daemon (reference link: http://learn.akae.cn/media/ch34s03.html)
#include <stdlib.h>#include <stdio.h>#include <fcntl.h>void daemonize(void){     pid_t  pid;     /*     * Become a session leader to lose controlling TTY.     */     if ((pid = fork()) < 0) {          perror("fork");          exit(1);     } else if (pid != 0) /* parent */          exit(0);     setsid();     /*     * Change the current working directory to the root.     */     if (chdir("/") < 0) {          perror("chdir");          exit(1);     }     /*     * Attach file descriptors 0, 1, and 2 to /dev/null.     */     close(0);     open("/dev/null", O_RDWR);     dup2(0, 1);     dup2(0, 2);}int main(void){     daemonize();     while(1);}

1. General steps for creating daemon (reference link: http://learn.akae.cn/media/ch34s03.html)

Explanation: (1 ). fork is called for the first time to ensure that the subsequent setsid can be successfully called, because the prerequisite for successful call of setsid is that the current process cannot be the leader of the Process Group; otherwise,-1 is returned, to ensure that the current process is not the first process in the process group, you only need to use fork to call setsid. The child process created by fork belongs to the same process group as the parent process. The leader of the process group must be the first process, and the child process cannot be the first process of the reorganization, if you call setsid in a sub-process, the problem will not occur.
(2 ). the result of calling setsid () to call this function is: Make the calling Process (1) the first process of the new session (Session), (2) become the leader of a new process group. (3) No control terminal.
After setsid () is executed, the source code provided by apue performs the second fork (). Is this fork required? Apue provides the following explanations:
In System V-based systems, it is recommended that you call fork again and terminate the parent process. The second child process continues to run as the genie process. This ensures that the sprite process is not the first process in the dialog period. Therefore, according to the SVR rules (see section 9.6), it can prevent it from obtaining control terminals. To avoid obtaining a control terminal, you must specify o_noctty whenever you open a terminal device.
Return to section 9.6 of apue. The original book provides the following explanations:

Systems derived from UNIX System V allocate the controlling terminal for a session when the session leader opens the first terminal device that is not already associated with a session. This assumes
That the callOpenBy the session leader does not specifyO_nocttyFlag (section 3.3 ).

BSD-based systems allocate the controlling terminal for a session when the session leader CILSIOCTLWith a request argumentTiocsctty(The third argument is a null pointer ).
The session cannot already have a controlling terminal for this call to succeed. (normally, this callIOCTLFollows a callSetsid, Which guarantees that the process is a session leader without a controlling terminal.) The posix.1O_nocttyFlag
ToOpenIs not used by BSD-based systems, memory T in compatibility-mode support for other systems.

Reference link: http://webcache.googleusercontent.com/search? Q = cache: xgmowra0cnij: bytes
The second fork attack is to prevent being assigned to the controlling terminal device by the system when a terminal device is opened.
As long as you do not mess up open (or use o_noctty is not required for the second fork ).

Then again, how does one allocate controlling terminal in Linux?

Apue does not mention Linux here, but mentions the differences between BSD and system-v. linux and BSD are the same, using IOCTL to get controlling terminal, URL: http://linux.die.net/man/4/tty_ioctlTIOCSCTTY int Arg make the given tty the controlling tty of the current process.
To sum up, the second fork is not mandatory, and it is used for system-V system compatibility considerations. (1) In the system-VThe o_noctty flag is not specified when open is called., WhenSession Initiation ProcessWhen you open the first terminal device that has not been associated with a session, the System-V system assigns this terminal as the control terminal. (2) In the free-BSD system, when the first session process uses tiocssctty as the request parameter (3rd parameters are null pointers)When IOCTL is calledThe BSD-based system allocates control terminals for sessions.

  1. The first thing to do is callUmaskTo set the file mode Creation mask to 0. The file mode Creation mask that's inherited cocould be set to deny certain permissions. If the daemon process is
    Going to create files, it may be want to set specific permissions. for example, if it specifically creates files with group-read and group-write enabled, a file mode Creation mask that turns off either of these permissions wocould undo its efforts.

  2. CallForkAnd have the parentExit. This does several things. First, if the daemon was started as a simple shell command, having the parent terminate makes the shell think that
    Command is done. second, the child inherits the process group ID of the parent but gets a new process ID, so we're guaranteed that the child is not a process group leader. this is a prerequisite for the callSetsidThat is done next.

  3. CallSetsidTo create a new session. The three steps listed in section 9.5 occur. The process (a) becomes a session leader of a new session, (B) becomes the process group leader
    Of a new process group, and (c) has no controlling terminal.

    Under
    System vbased systems, some people recommend callingForkAgain at this point and having the parent terminate. The second child continues as the daemon. This guarantees that the daemon is not a session leader, which prevents it from acquiring a controlling
    Terminal under the System V Rules (section 9.6). Alternatively, to avoid acquiring a controlling terminal, be sure to specifyO_nocttyWhenever opening a terminal device.

  4. Change the current working directory to the root directory. The current working directory inherited from the parent cocould be on a mounted file system. Since daemons normally exist until the system
    Is rebooted, if the daemon stays on a mounted file system, that file system cannot be unmounted.

    Alternatively, some daemons might change the current working directory to some specific location, where they will do all their work. For example, line printer spooling daemons often change to their
    Spool directory.

  5. Unneeded file descriptors shoshould be closed. This prevents the daemon from holding open any descriptors that it may have inherited from its parent (which cocould be a shell or some other process). We
    Can use ourOpen_maxFunction (Figure 2.16) orGetrlimitFunction (section 7.11) to determine the highest Descriptor and close all descriptors up to that value.

  6. Some daemons open file descriptors 0, 1, and 2/Dev/nullSo that any Library Routines that try to read from standard input or write to standard output or standard error will have no effect.
    Since the daemon is not associated with a terminal device, there is nowhere for output to be displayed; nor is there anywhere to receive input from an interactive user. even if the daemon was started from an interactive session, the daemon runs in the background,
    And the login session can terminate without affecting the daemon. if other users log in on the same terminal device, we wouldn't want output from the daemon showing up on the terminal, and the users wouldn't have CT their input to be read by the daemon.


Apue daemon routine:
#include "apue.h"#include <syslog.h>#include <fcntl.h>#include <sys/resource.h>voiddaemonize(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);    /*     * Become a session leader to lose controlling TTY.     */    if ((pid = fork()) < 0)        err_quit("%s: can't fork", cmd);    else if (pid != 0) /* parent */        exit(0);    setsid();    /*     * Ensure future opens won't allocate controlling TTYs.     */    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");    if ((pid = fork()) < 0)        err_quit("%s: can't fork", cmd);    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)        err_quit("%s: can't change directory to /");    /*     * 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);    /*     * Initialize the log file.     */    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);    }}

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.