一、守护进程的概念
1.定义
在后台运行的特殊进程,运行的周期长(系统启动时运行,直到关机),不和用户交互。
2.会话和会话首进程
(1)会话:终端的打开就会创建一个会话。会话中包含了进程组,而进程组中又包含了多个进程。
(2)会话首进程:会话的第一个进程,会话首进程的pid是会话的id。(会话首进程pid标识该会话)。
3.进程组和组长进程
(1)进程组:存在于会话中。
(2)组长进程:一个进程组中,启动该组的第一个进程。该进程的pid就是该进程组的id。
二、守护进程的编程
(1)基本流程
①执行fork(),退出父进程
作用:退出原始进程,使得后续的会话创建不会受到原始进程的影响。
原因:要选择普通组员创建一个新会话如果选择当前父进程创建会话,则该父进程作为新会话首进程,新会话的id和原来进程相同。所以选择子进程来创建新会话。保证不会受到原来进程的影响。
②创建新会话setsid()
③再次执行fork(),退出父进程
原因:使得子进程不作为任何会话的首进程,确保不受任何终端影响。因为fork后,该进程变为孤儿进程被系统接管。
④修改当前路径到‘/’根目录,chdir("/"):避免卸载
⑤修改掩码umask(0):确保文件从创建时权限不会被限制
⑥关闭所有描述符
注意:需要与任何终端隔离。
(2)代码实现
利用守护进程,实现一个日志文件(每隔5s,将当前系统时间写入日志文件)
#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);
}
}