守护进程(daemon)是一类在后台运行的特殊进程, 用于执行特定的系统任务。 很多守护进程在系统引导的时候启动, 并且一直运行直到系统关闭。 另一些只在需要的时候才启动, 完成任务后就自动结束。
用户使守护进程独立于所有终端是因为, 在守护进程从一个终端启动的情况下, 这同一个终端可能被其他的用户使用。 例如, 用户从一个终端启动守护进程后退出, 然后另外一个人也登录到这个终端。 用户不希望后者在使用该终端的过程中, 接收到守护进程的任何错误信息。 同样, 由终端键入的任何信号(例如中断信号)也不应该影响先前在该终端启动的任何守护进程的运行。虽然让服务器后台运行很容易(只要 shell命令行以&结尾即可), 但用户还应该做些工作, 让程序本身能够自动进入后台, 且不依赖于任何终端。守护进程没有控制终端, 因此当某些情况发生时, 不管是一般的报告性信息, 还是需由管理员处理的紧急信息, 都需要以某种方式输出。Syslog 函数就是输出这些信息的标准方法, 它把信息发送给 syslogd 守护进程。
创建一个守护进程
有个基本要求:
1. 必须作为我们 init 进程的子进程
2. 不跟控制终端交互。
步骤:
1.使用 fork 函数创建一个新的进程, 然后让父进程使用 exit 函数直接退出(必须要的)
2.调用 setsid 函数。 (必须要的)
3.调用 chdir 函数, 将当前的工作目录改成根目录, 增强程序的健壮性。 (不是必须要的)
4.重设我们 umask 文件掩码, 增强程序的健壮性和灵活性(不是必须要的)
5.关闭文件描述符, 节省资源(不是必须要的)
6.执行我们需要执行的代码(必须要的)
实验代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(void)
{
pid_t pid;
// 步骤一: 创建一个新的进程
pid = fork();
//父进程直接退出
if (pid > 0)
{
exit(0);
}
if (pid == 0)
{
// 步骤二: 调用 setsid 函数摆脱控制终端
setsid();
// 步骤三: 更改工作目录
chdir("/");
// 步骤四: 重新设置 umask 文件源码
umask(0);
// 步骤五: 0 1 2 三个文件描述符
close(1);
close(2);
close(3);
// 步骤六: 执行我们要执行的代码
while (1)
{
}
}
return 0;
}
运行测试, 如下图所示: