守护进程
什么是守护进程
守护进程也称精灵进程( Daemon),是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。
在了解守护进程之前我们先需要知道一下几个概念
会话
操作系统调度的基本单位是进程,单个或多个进程组成进程组,单个或多个进程组则组成会话
getsid(0)//获得会话的ID,返回当前进程调用的会话ID
进程组
一个进程组中有一个组长进程和0个或多个组员进程,组长进程的进程ID等于其进程组ID。
getpgrp()//获得进程组的ID,就是进程组中的组长id
终端
终端与会话和进程的关系如下图
从图中可以看出在同一终端中,会话id都没有变,因为都一个终端始终是一个会话。bash就是这个会话的首进程(6025)。会话的id就是这个首进程的id。
然后我们通过fork()创建一个子进程,看看进程组组长id
可以看出父进程的id永远都是这个进程组的id。
如果一个终端一一个会话被掐断,那么会话中的所有进程都会被kill,不再存在。
编写守护进程
编写守护进程的一般步骤
(1)在父进程中执行 fork 并 exit 退出父进程;
(2)在子进程中调用 setsid 创建新的会话;
(3)再一次执行 fork,退出父进程(可以不做)
(4)在子进程中调用 chdir 函数,让根目录 ”/” 成为子进程的工作目录;
(5)在子进程中调用 umask 函数,设置进程的 umask 为 0;
(6)在子进程中关闭不需要的文件描述符
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<time.h>
void set_d()
{
pid_t pid=fork();
if(pid!=0)
{
exit(0);
}
setsid();
pid=fork();
if(pid!=0)
{
exit(0);
}
chdir("/");
umask(0);
int maxfd=gettablesize();//获得最大文件描述符数
for(int i=0;i<maxfd;i++)
{
close(i);
}
}
int main()
{
set_d();
while(1)
{
FILE *fp=fopen("/tmp/deamon.log"."a");
if(fp=NULL)
{
break;
}
time_t tv;
time(&tv);
fprintf(fp,"time is %s\n",asctime(localtime(&tv)));
fclose(fp);
sleep(5);
}
}