6

How to Create a Daemon on Linux

 2 years ago
source link: https://www.makeuseof.com/create-daemons-on-linux/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

How to Create a Daemon on Linux

By Fatih Küçükkarakurt Published 11 hours ago

Daemons are processes that silently run in the background on your machine. Here's how you can code your own daemons on Linux.

daemon running inside a Linux terminal

Daemons are processes that do not run directly under the control of the user but serve in the background. Usually, they start on system startup and run continuously until the system shuts down. The only difference between these and normal processes is that they do not send messages to the console or screen in any way.

Here's how you can create a daemon on a Linux machine.

A Brief Introduction to How Daemons Are Created

A lot of daemons run on the system and some familiar daemon examples are as follows:

  • crond: Makes commands run at the specified time
  • sshd: Allows login to the system from remote machines
  • httpd: Serves web pages
  • nfsd: Allows file sharing over the network

Also, daemon processes are usually named to end with the letter d, although it's not mandatory.

For a process to run as a daemon, the following path is followed:

  • Initial operations, such as reading configuration files or obtaining necessary system resources, must be performed before the process becomes a daemon. This way, the system can report the received errors to the user and the process will be terminated with an appropriate error code.
  • A background running process is created with init as its parent process. For this purpose, a sub-process is forked from the init process first, and then the upper process is terminated with exit.
  • A new session should open by calling the setsid function, and the process should be disconnected from the terminal.
  • All open file descriptors inherited from the parent process are closed.
  • Standard input, output, and error messages are redirected to /dev/null.
  • The working directory of the process must change.

What Are Daemon Sessions?

After logging into the system via a terminal, users can run many applications through the shell program. These processes should close when the user exits the system. The operating system groups these processes into session and process groups.

Each session consists of process groups. You can describe this situation as follows:

daemon-sessions-diagrams

The terminal where the processes receive their inputs and send their outputs is called the controlling terminal. A controlling terminal is associated with only one session at a time.

A session and the process groups in it have identification (ID) numbers; these identification numbers are the process identification numbers (PID) of the session and process group leaders. A child process shares the same group as its parent process. When multiple processes are communicating with the pipe mechanism, the first process becomes the process group leader.

Creating a Daemon Process on Linux

Here you will see how you can create a daemon function. For this purpose, you will create a function named _daemon. You can start by naming the application code that will run as a daemon as test.c, and the code that you will create the daemon function as daemon.c.

//test.c
#include <stdio.h>
int _daemon(int, int);
int main()
{
getchar();
_daemon(0, 0);
getchar();
return 0;
}
//daemon.c
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fs.h>
#include <linux/limits.h>
int _daemon(int nochdir, int noclose) {
pid_t pid;
pid = fork(); // Fork off the parent process
if (pid < 0) {
exit(EXIT_FAILURE);
}
if (pid > 0) {
exit(EXIT_SUCCESS);
}
return 0;
}

To create a daemon, you need a background process whose parent process is init. In the code above, _daemon creates a child process and then kills the parent process. In this case, your new process will be a subprocess of init and will continue to run in the background.

Now compile the application with the following command and examine the status of the process before and after _deamon is called:

gcc -o test test.c daemon.c

Run the application and switch to a different terminal without pressing any other keys:

./test

You can see that the values related to your process are as follows. Here, you'll have to use the ps command to get process-related information. In this case, the _daemon function has not been called yet.

ps -C test -o "pid ppid pgid sid tty stat command"
# Output
PID PPID PGID SID TT STAT COMMAND
10296 5119 10296 5117 pts/2 S+ ./test

When you look at the STAT field, you see that your process is running but waiting for an off-schedule event to occur which will cause it to run in the foreground.

Abbreviation Meaning
S Waiting asleep for an event to happen
T Application stopped
s Session leader
+ The application is running in the foreground

You can see that the parent process of your application is the shell as expected.

ps -jp 5119                                 
# Output
PID PGID SID TTY TIME CMD
5119 5119 5117 pts/2 00:00:02 zsh

Now return to the terminal where you are running your application and press Enter to invoke the _daemon function. Then look at the process information on the other terminal again.

ps -C test -o "pid ppid pgid sid tty stat command"
# Output
PID PPID PGID SID TT STAT COMMAND
22504 1 22481 5117 pts/2 S ./test

First of all, you can say that the new subprocess is running in the background since you do not see the + character in the STAT field. Now examine who is the parent process of the process using the following command:

ps -jp 1                                      
​​​​​​​# Output
PID PGID SID TTY TIME CMD
1 1 1 ? 00:00:01 systemd

You can now see that the parent process of your process is the systemd process. It is mentioned above that for the next step, a new session should open and the process should be disconnected from the control terminal. For this, you use the setsid function. Add this call to your _daemon function.

The piece of code to add is as follows:

if (setsid() == -1) 
return -1;

Now that you've inspected the state before _daemon called, you can now remove the first getchar function in the test.c code.

//test.c
#include <stdio.h>
int _daemon(int, int);
int main()
{
_daemon(0, 0);
getchar();
return 0;
}

After compiling and running the application again, go to the terminal where you made your reviews. The new status of your process is as follows:

ps -C test -o "pid ppid pgid sid tty stat command"
​​​​​​​# Output
PID PPID PGID SID TT STAT COMMAND
25494 1 25494 25494 ? Ss ./test

The ? sign in the TT field indicates that your process is no longer connected to a terminal. Notice that the PID, PGID, and SID values of your process are the same. Your process is now a session leader.

In the next step, change the working directory to the root directory according to the value of the argument you passed. You can add the following snippet to the _daemon function for this:

if (!nochdir) {
if (chdir("/") == -1)
return -1;
}

Now, according to the argument passed, all file descriptors can be closed. Add the following code to the _daemon function:

#define NR_OPEN 1024
if (!noclose) {
for (i = 0; i < NR_OPEN; i++)
close(i);
open("/dev/null", O_RDWR);
dup(0);
dup(0);
}

After all file descriptors are closed, new files opened by daemon will be shown with the descriptors 0, 1, and 2 respectively. In this case, for example, the printf commands in the code will be directed to the second opened file. To avoid this, the first three identifiers point to the /dev/null device.

In this case, the final state of the _daemon function will be as follows:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
int _daemon(void) {
// PID: Process ID
// SID: Session ID
pid_t pid, sid;
pid = fork(); // Fork off the parent process
if (pid < 0) {
exit(EXIT_FAILURE);
}
if (pid > 0) {
exit(EXIT_SUCCESS);
}
// Create a SID for child
sid = setsid();
if (sid < 0) {
// FAIL
exit(EXIT_FAILURE);
}
if ((chdir("/")) < 0) {
// FAIL
exit(EXIT_FAILURE);
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
while (1) {
// Some Tasks
sleep(30);
}
exit(EXIT_SUCCESS);
}

Here's an example of a code snippet that runs the sshd application as a daemon:

...
if (!(debug_flag || inetd_flag || no_daemon_flag)) {
int fd;
if (daemon(0, 0) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
/* Disconnect from the controlling tty. */
fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
if (fd >= 0) {
(void) ioctl(fd, TIOCNOTTY, NULL);
close(fd);
}
}
...

Daemons Are Important for Linux System Programming

Daemons are programs that perform various actions in a predefined manner set in response to certain events. They run silently on your Linux machine. They are not under the direct control of the user and each service running in the background has its daemon.

It is important to master daemons to learn the kernel structure of the Linux operating system and to understand the working of various system architectures.

About The Author
624db80f0078d-profile.jpg?fit=crop&w=100&h=100

Fatih Küçükkarakurt (5 Articles Published)

An engineer and software developer who is a fan of math and technology. He has always liked computers, mathematics and physics. He has developed game engine projects as well as machine learning, artificial neural networks and linear algebra libraries. Moreover continues to work on machine learning and linear matrices.

More From Fatih Küçükkarakurt

Subscribe to our newsletter

Join our newsletter for tech tips, reviews, free ebooks, and exclusive deals!

Click here to subscribe

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK