一、定义
Linux Daemon(守护进程)是运行在后台的一种特殊进程,也称后台服务进程。 它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程不会因为终端的关闭而关闭,直至整个系统关闭后才会关闭。
二、那么为什么要引入守护进程呢?
由于在 linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依赖这个终端,这个终端就称为这些进程的控制终端。
当控制终端被关闭时,相应的进程都会自动关闭。但是守护进程却能突破这种限制,它被执行开始运转,直到整个系统关闭时才退出。
三、守护进程的特性
- 守护进程最重要的特性是后台运行。
- 其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符、控制终端、会话和进程组、工作目录已经文件创建掩码等。这些环境通常是守护进程从父进程那里继承下来的。
- 守护进程的启动方式。
四、创建守护进程的两种方式
创建守护进程,工作目录切换到 /
目录,将stdin、stdout、stderr屏蔽。不会随着终端的关闭而关闭,系统全部关闭后才会关闭。创建完守护进程后,我们在while函数里写守护进程需要执行的代码即可。
1. 逐步配置守护进程。
(1)让子进程变为孤儿进程(即父进程退出,子进程继续运行)。
(2)使用系统函数 setsid(),在子进程中创建新会话。
setsid()的作用:A.让进程摆脱原会话的控制,B.让进程摆脱原进程组的控制,C.让进程摆脱原控制终端的控制;
(3)改变当前的工作目录为根目录。以确保守护进程不会占用卸载的文件系统。
(4)重设文件权限掩码,以确保守护进程创建的文件有预期的权限。
(5)关闭标准流的文件描述符。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
void mydaemon()
{
pid_t pid;
// 1.创建子进程,父进程退出。
pid=fork();
if(pid >0) exit(0);
// 2.在子进程中创建新的会话
setsid();
// 3.改变当前的工作目录为根目录
chdir("/");
// 4.重设文件权限掩码
umask(0);
// 5.关闭所有不需要的文件描述符 .0-stdin 1-stdout 2-stderr
close(0);
close(1);
close(2);
}
int main(int argc,char **argv)
{
mydaemon();
while(1){
//守护进程的功能实现。
}
}
2. 利用系统函数创建守护进程。
由于逐步配置守护进程过于繁琐,我们可以直接使用系统函数来创建守护进程。
int daemon(int nochdir, int noclose);
//nochdir:=0 。将当前目录更改至“/”
//noclose:=0 。将标准输入、标准输出、标准错误重定向至空设备“/dev/null”,任何写入到 /dev/null 的数据都会被丢弃。
例程:
main函数返回-1时直接结束该代码,并不会继续执行下面的代码。由于我们下面打开创建文件时处于根目录下,我们作为普通用户无法创建文件,所以执行命令的时候需要加上sudo
来执行。或者将下面文件地址换到家目录下。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv)
{
int ret;
FILE *fp;
int i=0;
ret=daemon(0,0); //这里已经创建好了守护进程。
if(ret<0) return -1;
while(1)
{
//下面为守护进程实现的功能,即每隔1s想文件里写入数据。
fp=fopen("log.txt","a+");
if(fp==NULL) return -1;
fprintf(fp,"%d",i++);
fclose(fp);
sleep(1);
}
}