Writing Linux Daemon Process In C

Trinity's Avatar author of Writing Linux Daemon Process In C
This is an article on Writing Linux Daemon Process In C in C.

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 like this
0
lionaneesh's Avatar, Join Date: Mar 2010
Invasive contributor
Nice Article!
0
Scripting's Avatar, Join Date: Jun 2010
John Hoder
Good article, keep it up!
0
karthikp's Avatar, Join Date: Sep 2011
Newbie Member
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.