Linux——守护进程

一、守护进程的概念

1.定义

在后台运行的特殊进程,运行的周期长(系统启动时运行,直到关机),不和用户交互。

2.会话和会话首进程

(1)会话:终端的打开就会创建一个会话。会话中包含了进程组,而进程组中又包含了多个进程。

(2)会话首进程:会话的第一个进程,会话首进程的pid是会话的id。(会话首进程pid标识该会话)。

3.进程组和组长进程

(1)进程组:存在于会话中。

(2)组长进程:一个进程组中,启动该组的第一个进程。该进程的pid就是该进程组的id。

二、守护进程的编程

(1)基本流程

①执行fork(),退出父进程

作用:退出原始进程,使得后续的会话创建不会受到原始进程的影响。

原因:要选择普通组员创建一个新会话如果选择当前父进程创建会话,则该父进程作为新会话首进程,新会话的id和原来进程相同。所以选择子进程来创建新会话。保证不会受到原来进程的影响。

②创建新会话setsid()

③再次执行fork(),退出父进程

原因:使得子进程不作为任何会话的首进程,确保不受任何终端影响。因为fork后,该进程变为孤儿进程被系统接管。

④修改当前路径到'/'根目录,chdir("/"):避免卸载

⑤修改掩码umask(0):确保文件从创建时权限不会被限制

⑥关闭所有描述符

注意:需要与任何终端隔离。

(2)代码实现

利用守护进程,实现一个日志文件(每隔5s,将当前系统时间写入日志文件)

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<time.h>
#include<sys/types.h>
#include<sys/stat.h>
//守护进程:需要与任何终端隔离
//概念:在后台运行的特殊进程,运行时间长,不和用户交互。(在window中,守护进程也称为服务)
//编程流程: 
int main()
{
    //1.执行fork(),退出父进程
    //目的:退出原始进程,使得后续的会话创建不会受到原始进程的影响
    pid_t pid=fork();//fork,产生子进程
    if(pid!=0)//退出父进程
    {
        exit(0);
    }
    //2.创建新会话
    setsid();//此时子进程是会话首进程,也是组长进程,确保不受终端的干扰
    //3.再次执行fork(),退出父进程
    //子进程为孤儿进程,确保不会成为会话首进程
    pid=fork();
    if(pid!=0)
    {
        exit(0);
    }
    //4.修改当前路径到'/'根目录,避免卸载
    chdir("/");
    //5.修改掩码,确保文件从创建时权限不会被限制
    umask(0);

    //6.获取打开文件描述符的最大数目
    int maxfd=getdtablesize();

    //7.关闭所有描述符
    for(int i=0;i<maxfd;i++)
    {
        close(i);
    }

    //每隔5s,将当前系统时间写入到日志文件中
    while(1)
    {
        //获取当前时间
        time_t tv;
        time(&tv);//表示秒数
        FILE* fp=fopen("/tmp/shouhud.log","a");//以追加的模式打开文件,确保每次写入的时间都在文件末尾,不会覆盖之前的内容
        //localtime:将时间转化为本地时间tm结构
        //asctime:将tm结构格式转化为字符串
        //fprintf:将格式化的时间字符串写入文件
        fprintf(fp,"Time is %s",asctime(localtime(&tv)));
        fclose(fp);
        //暂停一定时间
        sleep(5);
    }

}

(3)运行截图