以下是一个简单的C语言守护进程代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
void handle_signal(int signum) {
if (signum == SIGTERM) {
printf("Daemon process terminated.\n");
exit(0);
}
}
int main() {
pid_t pid;
// 创建子进程
pid = fork();
// 如果出现错误,退出
if (pid < 0) {
exit(1);
}
// 父进程退出
if (pid > 0) {
exit(0);
}
// 在子进程执行以下代码
// 设置文件权限掩码,防止文件被其他用户访问
umask(0);
// 创建新的会话,使该进程成为会话首进程
if (setsid() < 0) {
exit(1);
}
// 关闭标准输入、输出和错误输出文件描述符
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// 重定向标准输入、输出和错误输出到/dev/null
if (open("/dev/null", O_RDONLY) < 0) {
exit(1);
}
if (open("/dev/null", O_WRONLY) < 0) {
exit(1);
}
if (open("/dev/null", O_RDWR) < 0) {
exit(1);
}
// 注册信号处理函数,当接收到SIGTERM信号时退出
signal(SIGTERM, handle_signal);
// 守护进程的主要逻辑代码
while (1) {
// 运行你的程序逻辑
// 睡眠一段时间,以减少CPU占用率
sleep(1);
}
return 0;
}
这个代码示例中,首先创建了一个子进程,然后父进程退出,保证了子进程的独立性。接着子进程调用setsid()
函数创建一个新的会话,将该子进程设置为会话首进程。然后关闭标准输入、输出和错误输出文件描述符,并重定向它们到/dev/null
设备文件,这样可以防止输出到终端。最后,注册了一个信号处理函数,当接收到SIGTERM
信号时,退出守护进程。
在守护进程的主要逻辑代码部分,可以根据自己的需求编写实际的程序逻辑。这里只是一个简单的示例,每隔一秒睡眠一次。
守护进程是在后台运行的一种特殊进程,通常用于长期运行的服务或后台任务,它会在系统启动时自动启动,并独立于用户登录会话运行。
首先,代码中使用fork()
函数创建了一个子进程
fork()
函数会复制当前进程,包括代码、数据和堆栈,生成一个全新的进程副本。生成的子进程和父进程几乎是完全相同的,但它们有不同的进程ID(pid)。父进程中,fork()
函数返回子进程的pid,而在子进程中,fork()
函数返回0。
接下来
父进程调用exit()
函数退出,这样保证只有子进程在运行。退出父进程后,子进程成为孤儿进程,由init进程接管。
子进程调用setsid()
函数创建一个新的会话,并将自己设置为该会话的首进程。会话是一个或多个进程的组合,通常由一个或多个进程组成。setsid()
函数创建一个新的会话,会话首进程是当前进程,没有控制终端与之关联。这样可以脱离终端的控制,保证守护进程的独立性。
接着
子进程关闭标准输入、输出和错误输出文件描述符,并通过open()
函数将它们重定向到/dev/null
设备文件。/dev/null
设备文件是一个特殊文件,任何写入它的数据都会被丢弃,任何从它读取的数据都会返回空值。这样做可以防止守护进程的输出在终端上显示。
最后
子进程注册了一个信号处理函数,当接收到SIGTERM
信号时,调用exit()
函数退出守护进程。SIGTERM
是一个终止进程的信号,通常由操作系统或其他进程发送给进程,用于要求进程自行终止。通过注册信号处理函数,守护进程可以在接收到终止信号时做一些清理工作并正常退出。
总结
总而言之,这段代码实现了创建一个守护进程的过程,包括创建子进程、设置会话、重定向文件描述符和注册信号处理函数。守护进程的作用是在后台运行,并且独立于用户登录会话,通常用于长期运行的服务或后台任务。