版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41026740/article/details/83353321
一、守护进程的相关定义
守护进程:也称为精灵进程,运行在后台的一种特殊进程。守护进程独立于控制终端并且周期性的执行某种任务或者等待处理发生的事件。所以守护进程不因为用户、终端或其他的变化而受影响。
守护进程的特点: 1. 运行周期长
2.在后台运行
3.不与用户交互
会话:一个或多个进程组的集合。用户从登录到退出期间的所有进程都属于一个会话期。会话id = 会话首进程的pid
进程组:一个或多个进程的集合。进程组的id=父进程的id。即父进程就是进程组长。
创建守护进程的必要性:打开终端,运行的第一个程序为bash。若关闭终端,整个会话就会结束。为了防止会话意外结束或其他,可以创建一个新的会话。
创建新会话的条件:只能是普通的组员进程才可创建新会话。不能是会话首进程或进程组长。
二、守护进程的编程流程
1.fork() 创建子进程,退出父进程
- 使所有工作在子进程中进行,形式上脱离了控制终端。如果进程是以shell命令方式从前台启动,从父进程终止时,shell就认为命令已经完成。这可以自动使子进程在后台运行。子进程继承了父进程的进程组号,但它拥有自己的进程号。这就保证了此子进程不是进程组长。可以进行下一步创建新会话。
2.setsid() 在子进程中创建新会话
- 使子进程完全独立出来,脱离控制。
3.fork() 退出父进程,失去进程组长身份
- 失去进程组长身份,称为普通组员进程。第二次fork的目的是确保守护进程来即使打开一个终端设备,也不会自动获得控制终端。
4.chdir("/") 改变当前工作路径至根目录下
- 防止占用可卸载的文件系统
5.umask(0) 将文件掩码清零
- 将文件模式创建屏蔽字设置为0
- 拒绝某些权限,增加守护进程灵活性
6.close() 关闭文件描述符
关闭守护进程从运行它的进程(通常为shell)继承而来打开的文件描述符。
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
//创建守护进程
int main()
{
pid_t pid = fork(); //创建子进程,退出父进程
if(pid != 0)
{
exit(0);
}
setsid(); //创建一个新会话
pid = fork(); //退出父进程,失去进程组长身份
if(pid != 0)
{
exit(0);
}
chdir("/"); //改变当前工作目录至根目录下
umask(0); //文件掩码清零
int maxfd = getdtablesize();
int i = 0;
for(; i<maxfd; i++)
{
close(i);
}
while(1)
{
FILE *fp = fopen("tmp/tiantian.log","a"); //fopen里a表示追加
if(fp == NULL)
{
break; //创建失败
}
time_t t;
time(&t); //获取当前时间,从1970.1.1开始计算
fprintf(fp,"current time:%s",asctime(localtime(&t)));
fclose(fp);
sleep(5);
}
exit(0);
}
运行命令:
cd /tmp 到根目录tmp下
tail -f tiantian.log //五秒钟刷新一次
运行结果: