Creating Linux Daemons with Filesystem Monitoring Capabilities

Nov 22, 2025 · Programming · 18 views · 7.8

Keywords: Linux Daemon | Filesystem Monitoring | inotify | systemd | Process Management

Abstract: This comprehensive guide explores the complete process of creating daemon processes in Linux systems, focusing on double-fork technique, session management, signal handling, and resource cleanup. Through a complete implementation example of a filesystem monitoring daemon, it demonstrates how to build stable and reliable background services. The article integrates systemd service management to provide best practices for daemon deployment in modern Linux environments.

Fundamental Concepts of Daemon Processes

In Linux systems, a daemon process is a special type of process that runs in the background, typically not associated with any controlling terminal. These processes are commonly used to provide system services such as network services, logging, or filesystem monitoring. Daemon process design must follow specific conventions to ensure stability and reliability.

Detailed Steps for Daemon Creation

Creating a standard Linux daemon process requires following a series of strict steps that ensure the process runs correctly in the background and remains unaffected by terminal sessions.

First Fork Operation

Begin by creating a child process through the fork system call, with the parent process exiting immediately. This step ensures the child process runs in the background and detaches from the original process group. In code implementation, proper handling of fork return values is essential: child process returns 0, parent process returns child's PID, and error returns -1.

pid_t pid = fork();
if (pid < 0) {
    exit(EXIT_FAILURE);
}
if (pid > 0) {
    exit(EXIT_SUCCESS);
}

Creating New Session

Use the setsid system call to create a new session, making the process a session leader. This step is crucial as it ensures the process completely detaches from the original controlling terminal. After successful setsid call, the process obtains new session ID and process group ID.

if (setsid() < 0) {
    exit(EXIT_FAILURE);
}

Signal Handling Configuration

Daemon processes need to properly handle various signals, particularly those that could cause process termination. Typically, SIGCHLD signal should be ignored to prevent zombie processes, while other signals should be handled according to specific requirements.

signal(SIGCHLD, SIG_IGN);
signal(SIGHUP, SIG_IGN);

Second Fork Operation

Perform another fork operation to prevent the process from reacquiring a controlling terminal. Only session leaders can acquire controlling terminals, so the second fork ensures the final daemon process is not a session leader.

pid = fork();
if (pid < 0) {
    exit(EXIT_FAILURE);
}
if (pid > 0) {
    exit(EXIT_SUCCESS);
}

Working Directory and File Permissions

Change the working directory to root or another secure directory to avoid issues caused by unmounted mount points. Simultaneously set appropriate file creation mask to ensure subsequently created files have correct permissions.

umask(0);
chdir("/");

File Descriptor Cleanup

Close all file descriptors inherited from the parent process, including standard input, standard output, and standard error output. This step prevents resource leaks and unexpected file operations.

for (int x = sysconf(_SC_OPEN_MAX); x >= 0; x--) {
    close(x);
}

Filesystem Monitoring Daemon Implementation

Based on the aforementioned daemon framework, we can implement a specialized daemon for monitoring filesystem changes. This process uses the inotify mechanism to listen for filesystem events.

inotify Initialization

First, initialize the inotify instance and add directories to monitor. inotify provides an efficient filesystem event monitoring mechanism that can detect file creation, modification, deletion, and other operations in real-time.

int inotify_fd = inotify_init();
if (inotify_fd < 0) {
    syslog(LOG_ERR, "inotify initialization failed");
    exit(EXIT_FAILURE);
}

int watch_desc = inotify_add_watch(inotify_fd, "/path/to/monitor", 
                                  IN_CREATE | IN_MODIFY | IN_DELETE);

Event Handling Loop

The daemon enters the main loop, continuously listening for filesystem events. When changes are detected, relevant information is written to the system log.

while (1) {
    char buffer[4096];
    ssize_t length = read(inotify_fd, buffer, sizeof(buffer));
    
    if (length > 0) {
        struct inotify_event *event = (struct inotify_event *)buffer;
        if (event->len) {
            syslog(LOG_NOTICE, "File change: %s", event->name);
        }
    }
    
    sleep(1);  // Avoid excessive CPU usage
}

systemd Service Integration

In modern Linux systems, systemd has become the standard service management tool. By creating systemd service unit files, daemon process lifecycle can be better managed.

Service Unit File Configuration

Create a basic systemd service file defining service startup type, execution command, and other relevant parameters.

[Unit]
Description=Filesystem Monitoring Daemon
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/filesystem-monitor
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Service Management Commands

Use systemctl commands to manage daemon services, including starting, stopping, restarting, and checking status.

# Enable service
sudo systemctl enable filesystem-monitor.service

# Start service
sudo systemctl start filesystem-monitor.service

# Check service status
sudo systemctl status filesystem-monitor.service

Logging Strategy

Since daemon processes lack controlling terminals, they must use system logging mechanisms to record runtime information. syslog provides standard logging interfaces supporting different levels of log messages.

openlog("filesystem-monitor", LOG_PID, LOG_DAEMON);
syslog(LOG_NOTICE, "Daemon started");
// ... Running logic
syslog(LOG_NOTICE, "Daemon terminated");
closelog();

Error Handling and Signal Management

Robust daemon processes require comprehensive error handling mechanisms and signal management strategies. Beyond ignoring unnecessary signals, critical signals must be handled to ensure proper process shutdown.

void signal_handler(int sig) {
    switch(sig) {
        case SIGTERM:
            syslog(LOG_NOTICE, "Received termination signal, shutting down...");
            // Clean up resources
            closelog();
            exit(EXIT_SUCCESS);
            break;
        default:
            break;
    }
}

// Register signal handler
signal(SIGTERM, signal_handler);

Performance Optimization Considerations

In actual deployment, the performance impact of daemon processes must be considered. Through appropriate polling intervals, event batching, and resource limitations, daemon processes can provide effective monitoring without significantly affecting system performance.

Security Best Practices

Daemon processes typically run with privileged identities, making security paramount. It's recommended to follow the principle of least privilege, restrict process access permissions, and conduct regular security audits.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.