在Linux中,我想添加一个无法停止的守护进程,该守护进程监视文件系统更改.如果检测到任何更改,它应该将启动时所在控制台的路径+换行符写入其中.
守护进程在后台工作,并且(通常…)不属于TTY这就是为什么你不能以你可能想要的方式使用stdout/stderr.
除此之外,还有几百种方法可以对一个进程进行后台监控.
如果我没记错,这些步骤是:
- fork off the parent process & let it terminate if forking was successful. -> Because the parent process has terminated, the child process now runs in the background.
- setsid-创建一个新会话.调用流程将成为新会话的负责人和新流程组的流程组长.该进程现在已与其控制终端(CTTY)分离.
- Catch signals-忽略和/或处理信号.
- fork again&;让父进程终止,以确保摆脱会话 bootstrap 进程.(只有会议负责人才能再次获得TTY.)
- chdir-更改守护进程的工作目录.
- umask-根据守护进程的需要更改文件模式掩码.
- close-关闭可能从父进程继承的所有打开的文件描述符.
给您一个起点:看看这段显示基本步骤的框架代码.现在还可以在giHub:Basic skeleton of a linux daemon上派生此代码
/*
* daemonize.c
* This example daemonizes a process, writes a few log messages,
* sleeps 20 seconds and terminates afterwards.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
static void skeleton_daemon()
{
pid_t pid;
/* Fork off the parent process */
pid = fork();
/* An error occurred */
if (pid < 0)
exit(EXIT_FAILURE);
/* Success: Let the parent terminate */
if (pid > 0)
exit(EXIT_SUCCESS);
/* On success: The child process becomes session leader */
if (setsid() < 0)
exit(EXIT_FAILURE);
/* Catch, ignore and handle signals */
//TODO: Implement a working signal handler */
signal(SIGCHLD, SIG_IGN);
signal(SIGHUP, SIG_IGN);
/* Fork off for the second time*/
pid = fork();
/* An error occurred */
if (pid < 0)
exit(EXIT_FAILURE);
/* Success: Let the parent terminate */
if (pid > 0)
exit(EXIT_SUCCESS);
/* Set new file permissions */
umask(0);
/* Change the working directory to the root directory */
/* or another appropriated directory */
chdir("/");
/* Close all open file descriptors */
int x;
for (x = sysconf(_SC_OPEN_MAX); x>=0; x--)
{
close (x);
}
/* Open the log file */
openlog ("firstdaemon", LOG_PID, LOG_DAEMON);
}
int main()
{
skeleton_daemon();
while (1)
{
//TODO: Insert daemon code here.
syslog (LOG_NOTICE, "First daemon started.");
sleep (20);
break;
}
syslog (LOG_NOTICE, "First daemon terminated.");
closelog();
return EXIT_SUCCESS;
}
+------+------+------+------+-----+-------+------+------+------+-----+
| PPID | PID | PGID | SID | TTY | TPGID | STAT | UID | TIME | CMD |
+------+------+------+------+-----+-------+------+------+------+-----+
| 1 | 3387 | 3386 | 3386 | ? | -1 | S | 1000 | 0:00 | ./ |
+------+------+------+------+-----+-------+------+------+------+-----+
What you should see here is:
- 守护程序没有控制终端(TTY = ?)
- 父进程ID(PPID)是1(init进程)
- PID != SID,这意味着我们的流程不是会议负责人
- 因为PID!=SID我们的流程can't take control of a TTY again
Reading the syslog:
firstdaemon[3387]: First daemon started.
firstdaemon[3387]: First daemon terminated.
A note:
In reality you would also want to implement a signal handler and set up the logging properly (Files, log levels...).
Further reading: