Process Linux system programming (eight): daemon explain and create, daemon (use

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

A, daemon

Linux Daemon(Daemon) is running in a special process of background. It is independent of the control terminal and periodically to perform some task or wait for the processing of certain events. It does not require user input will be able to run and provide a service, not for the entire system is to provide services to a user program. Most of the server of the Linux system is realized by the daemon. Common daemon include system log process syslogd, web server, httpd server and database server, sendmail mysqld etc.

Daemon start running when the system starts up, unless forced termination, kept running until the system shutdown. Daemon (root) often with super user privileges to run, because they have to use special port (1-1024) or access to certain resources.

A guardian's parent process is init process, because it is the real father process in the fork sub process precedes the child process exit quit, so it is a init inherited orphaned process. Daemon is non interactive programs, no controlling terminal, so any output, whether to output stdout standard output device or the standard error device stderr need special treatment.

Name daemon usually end with D, such as sshd, xinetd, crond etc.

Two, create a daemon process

We must first understand some basic concepts:

Process group :

Session:

Session (session) is a collection of one or more process group.

setsid()The establishment of a session can function:

 If, call the setsid process is not a process group leader, this function creates a new session.

(1)This process into the session of the first process

(2)This process becomes a new process group leader process.

(3)This process does not have a control terminal, if the call setsid before, this process has a control terminal, then with the terminal connection is released. If the process is a process group leader, this function returns an error.

(4)In order to ensure that this point, we first call fork () and exit (), the only child process in operation

Now we give the steps required to create a daemon:

The preparation of general steps daemon:

(1)Implementation of fork and exit in the parent process,

(2)Create a setsid function call new session in the child process,

(3)Call the chdir function in the child process, let the root directory "/" become children of the working directory of the process,

(4)Call the umask function in the child process, the process of setting umask to 0,

(5)Do not need any of the file descriptor is closed in the child process

Explain:

The 1 running in the background.
In order to avoid hang control terminal will Daemon into the background execution. Method is to process calls fork to make the parent process terminates, let Daemon perform background in the child process.
if(pid=fork())
Exit (0); // is the parent process, the end of the parent process, sub process continue
2. from the control terminal, login session and process group
It is necessary to introduce Linux in the process and control terminal, the relationship between the logon session and process group: the process is a process group, process group number (GID) is the head of the process process ID (PID). The logon session can contain multiple process groups. These share a control terminal process group. The control terminal is usually to create the login terminal process.
Control terminal, login session and process group is usually inherited from the parent process. Our objective is to get rid of them, so that it is not influenced by them. Method is based on the first point, call setsid () so that the process of becoming a session leader:
setsid();
Description: when the process is a session leader (setsid) call failed. But the first point is to ensure the process is not the session leader. Setsid () is successful, process to become the new leader and new process session leader, and with the original log out session and process group. As the session process of the exclusive control of the terminal, at the same time from the process and the control terminal.

Now, the process has become a non terminal session leader. But it can re apply to open a control terminal. The process is no longer a session leader to prohibit the process to re open the control terminal:
if(pid=fork())
Exit (0); // the end of the first sub process, second sub processes continue to (second sub process is no longer a session leader)
The file descriptor
4. close open
Process from the parent process that created it inherited the open file descriptor. If not closed, will be a waste of system resources, cause the file system to process where the unable to unload and cause unforeseen errors. Close them according to the following methods:
For (i=0; I to close the open file descriptor (I); > close;
>5. to change the current working directory
The process of activities, not the file system where its working directory to unload. The general need to change working directory to the root directory. For the need to dump core, write operation log process will work directory changes into a specific directory such as /tmpchdir (" /")
6. reset file creation mask
The
process from the parent process that created it inherited the file creation mask. It may modify the daemon to access files created position. To prevent this, remove the file creation mask (0): umask;
7. SIGCHLD signal processing
SIGCHLD signal handling is not required. But for some of the process, especially the server process often comes at the request of the process of handling requests for generators. If the parent does not wait for the child process ends, the child process will become a zombie process (zombie) to take up system resources. If the parent process to wait for the end of the child process, will increase the burden of the parent process, concurrent performance of the server process. In the Linux can be easily set the operation of the signal SIGCHLD SIG_IGN.
signal(SIGCHLD,SIG_IGN);
In this way, the kernel will not produce the zombie in the sub process is completed. This is different with BSD4, BSD4 must be explicitly wait for the child process to release the end of zombie.

Three, create a daemon

Before creating our first understand setsid (use):

  #include <unistd.h>

       pid_t setsid(void);

DESCRIPTION
       setsid()  creates a new session if the calling process is not a process
       group leader
The calling process is the leader of  the  new  session,
       the  process group leader of the new process group, and has no control-
       ling tty
The process group ID and session ID of the  calling  process
       are set to the PID of the calling process
The calling process will be
       the only process in this new process group and in this new session
.

//The calling process must be non current process group leader, after the call, to produce a new session, only one process group and the session, and the process group leader for the calling process, no control terminal, the new group ID and session ID is set to the PID of the calling process

RETURN VALUE
       On success, the (new) session ID of the calling  process  is  returned.
       On  error,  (pid_t) -1  is  returned,  and errno is set to indicate the
       error.

Now according to the steps to create a daemon:

The following program is to create a daemon, then use this daemon each one minute time to write the daemon.log file

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>

#define ERR_EXIT(m) \
do\
{\
    perror(m);\
    exit(EXIT_FAILURE);\
}\
while (0);\

void creat_daemon(void);
int main(void)
{
    time_t t;
    int fd;
    creat_daemon();
    while(1){
        fd = open("daemon.log",O_WRONLY|O_CREAT|O_APPEND,0644);
        if(fd == -1)
            ERR_EXIT("open error");
        t = time(0);
        char *buf = asctime(localtime(&t));
        write(fd,buf,strlen(buf));
        close(fd);
        sleep(60);
            
    }
    return 0;
}
void creat_daemon(void)
{
    pid_t pid;
    pid = fork();
    if( pid == -1)
        ERR_EXIT("fork error");
    if(pid > 0 )
        exit(EXIT_SUCCESS);
    if(setsid() == -1)
        ERR_EXIT("SETSID ERROR");
    chdir("/");
    int i;
    for( i = 0; i <3; ++i)
    {
        close(i);
        open("/dev/null", O_RDWR);
        dup(0);
        dup(0);
    }
    umask(0);
    return;
}


Result:

QQ截图20130713184143

The results show: when I was a normal user a.out, the process table and no new daemon, but when I take root user execution, successful, and in the / directory to create the daemon.log file, cat view is a write once every minute. Why only root execution, it is because when we create a daemon process, has been the current directory switch I / directory, so when creating a daemon.log file after me is actually / directory, it will not work, because the average user does not have permission, perhaps you will ask that you not wrong? There are in fact wrong, but we are creating the daemon will have the standard input and close the redirect to /dev/null, so can not see the error message.

Four, the use of daemon library functions () create a daemon

In fact, we can use daemon () function to create a daemon process, its function prototype:

#include <unistd.h>

int daemon(int nochdir, int noclose);


DESCRIPTION
       The daemon() function is for programs wishing to detach themselves from
       the controlling terminal and run in the background as system daemons.

       If nochdir is zero, daemon()  changes  the  process's  current  working
       directory to the root directory ("/"); otherwise,

       If  noclose is zero, daemon() redirects standard input, standard output
       and standard error to /dev/null; otherwise,  no  changes  are  made  to
       these file descriptors.

Function: create a daemon

Parameters:

nochdir: =0 will be changed to the current directory"/"

noclose: =0 will be the standard input, standard output, the standard error redirection to"/dev/null"

The return value:

Success: 0

Failure: -1

Now we use daemon () to rewrite the program:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>

#define ERR_EXIT(m) \
do\
{\
    perror(m);\
    exit(EXIT_FAILURE);\
}\
while (0);\

void creat_daemon(void);
int main(void)
{
    time_t t;
    int fd;
    if(daemon(0,0) == -1)
        ERR_EXIT("daemon error");
    while(1){
        fd = open("daemon.log",O_WRONLY|O_CREAT|O_APPEND,0644);
        if(fd == -1)
            ERR_EXIT("open error");
        t = time(0);
        char *buf = asctime(localtime(&t));
        write(fd,buf,strlen(buf));
        close(fd);
        sleep(60);
            
    }
    return 0;
}

When daemon (0,0) time:

QQ截图20130713190523

The results just, is only root to be successful, ordinary users to perform time fail to see the error message

Let daemon (0,1), is not close to the standard input and output results:

QQ截图20130713190932

You can see the error message

Let daemon (1,0), is not redirected, the results are as follows:

QQ截图20130713191221

The ordinary users to perform successful, thought no switch to / directory, have the authority

In fact, we can use we had just written, create a daemon program (default daemon) implementation:

The following code:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>

#define ERR_EXIT(m) \
do\
{\
    perror(m);\
    exit(EXIT_FAILURE);\
}\
while (0);\

void creat_daemon(int nochdir, int noclose);
int main(void)
{
    time_t t;
    int fd;
    creat_daemon(0,0);
    while(1){
        fd = open("daemon.log",O_WRONLY|O_CREAT|O_APPEND,0644);
        if(fd == -1)
            ERR_EXIT("open error");
        t = time(0);
        char *buf = asctime(localtime(&t));
        write(fd,buf,strlen(buf));
        close(fd);
        sleep(60);
            
    }
    return 0;
}
void creat_daemon(int nochdir, int noclose)
{
    pid_t pid;
    pid = fork();
    if( pid == -1)
        ERR_EXIT("fork error");
    if(pid > 0 )
        exit(EXIT_SUCCESS);
    if(setsid() == -1)
        ERR_EXIT("SETSID ERROR");
    if(nochdir == 0)
        chdir("/");
    if(noclose == 0){
            int i;
    for( i = 0; i <3; ++i)
    {
        close(i);
        open("/dev/null", O_RDWR);
        dup(0);
        dup(0);
    }

    umask(0);
    return;
}

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Rose at November 13, 2013 - 10:28 PM