一、实验目的
1、了解守护进程的生命周期及应用。
2、掌握编写守护进程的五个基本步骤。
二、实验原理
1、守护进程是运行在后台的一种特殊进程,用于周期性地执行某种任务或等待处理某些发生的事件。
2、守护进程生存期较长,常常在系统引导装入时启动,在系统关闭时终止。守护进程的名称通常以d结尾。
3、编写守护进程的五个步骤:
(1)fork()创建子进程,exit()退出父进程。
(2)setsid()在子进程中创建新会话,使子进程脱离原来的控制。
(3)chdir()改变当前的工作目录为根目录,防止可卸载的文件系统被占用。
(4)umask()设置文件权限掩码,防止继承来的文件创建屏蔽字,拒绝某些权限。
(5)close()关闭文件描述符,由于子进程从父进程继承一些打开的无用的文件,需要将其关闭,防止占用资源。
三、实验内容
1、编写守护进程test,test每5秒钟打印一个数字,定向输出到trush.txt。
2、编写并编译monitor.c,其功能为每5秒检测一次test是否正在运行;若未运行,则运行该程序。
3、先验证test是否能正常运行,需要执行test,然后用命令查看数字是否正常输出至trush.txt。
4、然后执行kill命令终止进程,使用命令查看test此时并未运行。
5、执行monitor,5秒钟后使用命令查看test此时已经运行。
选做部分:将编写的守护进程设置为开机自启动。
四、实验步骤
1、源程序(在目录下新建三个文件,目录可自己选择)
这里采用的目录为/home/usr/test/
1) test.c
#include<unistd.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<time.h>
void init_daemon()
{
int pid;
int i;
pid=fork();
if(pid < 0)
{
//创建错误,退出
exit(1);
}
else if(pid > 0)
{
//父进程退出
exit(0);
}
//使子进程成为组长
setsid();
pid=fork();
if(pid > 0)
{
//再次退出,使进程不是组长,这样进程就不会打开控制终端
exit(0);
}
else if(pid < 0)
{
exit(1);
}
//关闭进程打开的文件句柄
for(i=0;i<NOFILE;i++)
close(i);
//改变目录
chdir("/home/usr/test");
//重设文件创建的掩码
umask(0);
return;
}
void main()
{
FILE *fp;
int i=0;
init_daemon();
while(1)
{
i++;
fp=fopen("/home/usr/test/log/trush.txt","a");
if(fp>=0)
{
fprintf(fp,"%d\n",i);
fclose(fp);
}
sleep(5);
}
return;
}
2) monitor.c
#include<unistd.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<time.h>
void init_daemon()
{
int pid;
int i;
pid=fork();
if(pid<0)
{
//创建错误,退出
exit(1);
}
else if(pid>0)
{
//父进程退出
exit(0);
}
//使子进程成为组长
setsid();
pid=fork();
if(pid>0)
{
//再次退出,使进程不是组长,这样进程就不会打开控制终端
exit(0);
}
else if(pid<0)
{
exit(1);
}
//关闭进程打开的文件句柄
for(i=0;i<NOFILE;i++)
close(i);
//改变目录
chdir("/home/usr/test");
//重设文件创建的掩码
umask(0);
return;
}
// 得到trush.txt文件大小
int file_size()
{
FILE *fp=fopen("/home/usr/test/log/trush.txt","r");
if(!fp) return -1;
fseek(fp,0L,SEEK_END);
int size=ftell(fp);
fclose(fp);
return size;
}
void main()
{
FILE *fp;
time_t t;
init_daemon();
int size = file_size();
while(1)
{
sleep(5);
int size2 = file_size();
fp=fopen("/home/usr/test/log/monitor.log","a");
if(fp>=0)
{
time(&t);
fprintf(fp,"size =%d,%s\n",size, asctime(localtime(&t)));
fclose(fp);
}
if(size2 > size)
{
size = size2;
}
else
{
system("/home/usr/test/test");
}
}
return;
}
3) me.sh
/home/usr/test/monitor
4) 创建文件夹(千万不要忘了,要不后面无法正常执行)
mkdir log
2、编译文件并修改文件权限
gcc -c test.c
gcc -o test test.o
gcc -c monitor.c
gcc -o monitor monitor.o
- 将所有文件的权限修改为可读可写可操作
chmod 777 test.c test.o test monitor monitor.c monitor.o me.sh
3、设置开机自启动
1)编辑/etc/profile文件,命令如下:
sudo vim /etc/profile
2) 向文件中,添加如下内容:
4、验证是否正确运行
1) 使用reboot命令重启计算机
2) 验证monitor是否运行,使用如下命令:
ps -ef | grep monitor
查看结果:
3)验证test是否运行,使用如下命令:
ps -ef | grep test
查看结果:
4)使用kill命令终止进程:
可知,该进程已被结束。
5)monitor开机自启动,此时正在运行。等待5秒查看,test是否正确启动:
可知,test已被monitor再次启动。
6)查看输出日志文件:
trush.txt内容:
monitor.log内容:
至此结束!!!