Writing Linux Daemon Process In C

Discussion in 'C' started by Trinity, Jan 16, 2012.

  1. Trinity

    Trinity New Member

    Joined:
    Nov 23, 2011
    Messages:
    28
    Likes Received:
    11
    Trophy Points:
    3
    Occupation:
    Software Engineer

    What is Dameon Process?



    A Daemon process is a process which is not associated with any terminal and hence is supposed to run in background. Since, a daemon process involves background processing, it is recommended it should not include any user interaction. Therefore, it should be clear about its continuous processing not caring to wait for any input or to display any output. However, C programming does not define any such restrictions in its development as such. A daemon process developer should be well aware of its definition and ideal functionality before one starts the programming.

    A well known example of a daemon process could be a mail server, which runs in background and listening to ports to receive any mail anytime. Please note, a daemon process could be called as services on windows OS, but we are not talking about windows OS here, as things are pretty different there.

    Here in this tutorial, we shall be learning how to program a daemon process.

    The fork() call?



    Before, we begin programming on creating/handling processes, you should be well aware of the fork() C library call
    Code:
    pid_t fork()
    
    If you know it well, you can skip this section!

    fork() call initiates a new process. Process? Going back to basics, lets understand what is a process first. A process can be called as an execution context of a running program with its own process memory layout in the RAM. When we run any C-compiled executable

    On Linux through terminal as,
    Code:
    ./anyExe
    
    It starts a process with current terminal as its parent, i.e. this process is associated with this current terminal, and hence the process should terminate in case the terminal terminates.

    Also, every process has its unique process id called the "PID". You can check the various processes running through on linux,
    Code:
    ps -A
    
    Coming back to fork() call, it would create a new child process, with the calling process as its parent. The call returns the PID i.e. the unique process id of the newly created child process. However, from the point, where a fork() is called in the program, two processes begins to run i.e. both processes executes the same control flow, as to what follows the fork() call.

    For example, in the following code:
    Code:
    int var = 0;
    fork();
    var++;
    if (var == 1)
        printf("var is one\n");
    else
        printf("var is %d\n", var););
    
    Parent-child processes donot share local variables memory, hence the output of the above code snippet is
    Code:
    var is one
    var is one
    
    The printf() statements are executed twice, one by the parent process and other by the child process.

    Regarding more information about fork(), and what all is inherited by the child process can be found from the man page of fork().

    Writing daemon process in C



    For developing a daemon process program in linux, one should keep in mind following points:

    • Remove association of the daemon process with any terminal: The best way to disassociate any process from a terminal is by creating a child process and terminating its parent parent. Any process initiated through a terminal will have the terminal as its parent. Hence, any child process forked out of a terminal initiated process would have terminal as its grandparent.

      As in, in the following process hierachy,
      Code:
      Terminal > Process1 > childProcess2
      
      Terminating Process1 disassociates childProcess2 from its grandparent Terminal.
      Following source code illustrates the same:
      Code:
          pid = fork();// fork a new child process
      
          if (pid < 0) // A check to see if fork() succeeded?
          {
              printf("fork failed!\n");
              exit(1);
          }
      
          if (pid > 0)// its the parent process
          {
             printf("pid of child process %d \n", pid);
             exit(0); //terminate the parent process succesfully
          }
      
      Here, first of all, we fork() a new child process. In case, a fork() call fails, a negative value pid is returned, and therefore leads to a failure termination.

      Please note, the value of variable pid would be:
      • a unique PID for the main process (the parent). That is, pid would contain the PID of the newly created child process in the parent process eecution flow.
      • zero for the child process execution flow.
      We are terminating the parent process (where pid is a unique positive value) for the already mentioned reason, as to remove the association from the terminal. Hence, now its just the child process that continues to run as the daemon process.
    • Change the file mode maskings: Since, the newly created daemon process should be able to open, read and write any file anywhere, lets un-mask any file modes it has inherited as defaults. Thereby, we give all the file rights to the daemon process through the unmask call.
      Code:
      umask(0);
      
      Its generally a good practice to do the unmasking of file modes even in cases no file operations are involved by the daemon process.
    • Create a new session: Create a new session, so as the kernal could take care of the daemon process and identify it in the newly created session through its session id returned by this call.
      With this call, the daemon process is no longer a child process, but a process group leader now.
      Code:
          sid = setsid();//set new session
          if(sid < 0)
          {
              exit(1);
          }
      
      
      This call returns a unique session id which is a negative value in case of a failure. More information about the setsid() call are available ath its man page.
    • Close standard inputs, outputs and errors: Since, a daemon process does not involve any user interaction, it is highly recommended to explicitly close the standard file descriptors i.e. stdout, stdin and stderr.
      Code:
          close(STDIN_FILENO);
          close(STDOUT_FILENO);
          close(STDERR_FILENO);
      
    • A daemon process logic: There has to be a something for the daemon process to-do in the background, which is the logic of the daemon process. It could be anything based upon your requirement. The logic could be an infinite loop logic, i.e which keeps running in the background until the system kernal terminates. Or else, it could be a terminatory logic, which does its tasks and exits silently.

      In our example, lets just open a file and write into it after every 1 second for a total of 10 seconds.
      Code:
          fp = fopen ("mydaemonfile.txt", "w+");
          while (i < 10)
          {
              sleep(1);
              fprintf(fp, "%d", i);
              i++;
          }
          fclose(fp);
      
      Here, it opens a file in the current directory in write mode and writes out the value of 'i' after every 1 second. The process continues till 10 seconds and terminates silently closing the file.

    The Complete Program



    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <string.h>
    
    int main(int argc, char* argv[])
    {
        pid_t pid = 0;
        pid_t sid = 0;
        FILE *fp= NULL;
        int i = 0;
        pid = fork();// fork a new child process
    
        if (pid < 0)
        {
            printf("fork failed!\n");
            exit(1);
        }
    
        if (pid > 0)// its the parent process
        {
           printf("pid of child process %d \n", pid);
            exit(0); //terminate the parent process succesfully
        }
    
        umask(0);//unmasking the file mode
    
        sid = setsid();//set new session
        if(sid < 0)
        {
            exit(1);
        }
    
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
    
        fp = fopen ("mydaemonfile.txt", "w+");
        while (i < 10)
        {
            sleep(1);
            fprintf(fp, "%d", i);
            i++;
        }
        fclose(fp);
      
        return (0);
    }
    

    Running and Observing



    Compiling and running the program:
    Code:
    $gcc ProcessD.c -Wall -o ProcessD
    $./ProcessD
    
    Note, the control comes back to the terminal command prompt instantly.

    However, but the daemon process is running in the background which can be checked within next 10 secs as
    Code:
    ps -A | grep "ProcessD"
    
    Output for 10 seconds as
    Code:
     3137 ?        00:00:00 ProcessD
    
    Note, the output is nothing after 10 seconds, as the daemon process has terminated. Donot forget to check the newly created file 'mydaemonfile.txt' to see what daemon process did.

    A Note



    A daemon process inherits the same working directory as its terminated parent process. Hence, to avoid any unexpected results in case the current working directory of the terminated parent process is deleted, its always a good practise to change the current working directory of the daemon process to home or root.
     
    lionaneesh likes this.
  2. lionaneesh

    lionaneesh Active Member

    Joined:
    Mar 21, 2010
    Messages:
    848
    Likes Received:
    224
    Trophy Points:
    43
    Occupation:
    Student
    Location:
    India
    Nice Article!
     
  3. Scripting

    Scripting John Hoder

    Joined:
    Jun 29, 2010
    Messages:
    421
    Likes Received:
    57
    Trophy Points:
    0
    Occupation:
    School for life
    Location:
    /root
    Good article, keep it up!
     
  4. karthikp

    karthikp New Member

    Joined:
    Sep 3, 2011
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    Amazing stuff! I usually program in Java and haven't done much programming in C/C++. Recently, I started learning C++ and I'm quite interested in learning more. Writing daemon processes could come in handy someday.

    Anyways, a really well written article. Keep it up. :)
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice