守护进程:
独立于控制终端,在后台周期性的执行某些操作的进程。
特点:
不受用户登录/注销影响;
一般采用以d结尾的名字。
作用:
1、避免进程在执行过程中的信息在任何终端上显示;
2、避免进程被任何终端所产生的终端信息所打断。
通俗的说就是,想让某个进程不因为用户或终端或其他的变化而受到影响,那么就必须把这个进程变成一个守护进程。
创建:
1、fork子进程,终止父进程(必须执行)
2、在子进程中创建新会话(必须执行,通过setsid()函数创建新会话)
3、改变当前工作目录chdir(不必须,为了增强程序的健壮性)
4、重设文件掩码(不必须,子进程会继承父进程的文件掩码,可以增加程序的灵活性,用umask(0)方法)
5、关闭文件描述符(不必须,此进程脱离了终端,所以关闭标准输入(0)、输出(1)、错误输出(2),目的是释放资源)
6、执行核心内容(必须的,守护进程存在的必要性)
实例:
例:创建一个守护进程,每隔三秒钟获取一次系统时间,将这个时间写入磁盘文件。
思路:
1、创建子进程
2、设置定时器(三秒钟获取一次);或者用sleep睡眠3秒
3、捕捉定时器信号;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
void dowork()//回调函数
{
//得到当前时间
time_t curtime;
time(&curtime);
//格式化时间
char* pt = ctime(&curtime);
//char* pt = "hello world!";
//写入磁盘文件
int fd = open("/home/djh/linux/file.txt",O_CREAT | O_WRONLY | O_APPEND,0664);
write(fd,pt,strlen(pt)+1);
close(fd);
}
int main()
{
//创建子进程
pid_t pid = fork();
if(pid > 0)
{
//结束父进程
exit(1);
}
else if(pid == 0)
{
//子进程创建会话 变成守护进程
setsid();
//改变工作目录
chdir("/home/djh");//一般没用
//重置文件掩码
umask(0);
//关闭文件描述符
close(0);//写宏会好一点
close(1);
close(2);
//执行核心操作
/*//定时器做法
//注册信号捕捉
struct sigaction sig;
sig.sa_flags = 0;
sig.sa_handler = dowork;//处理信号的回调函数
sigemptyset(&sig.sa_mask);
sigaction(SIGALRM,&sig,NULL);
//创建定时器(sleep()也可以)
struct itimerval val;
//第一次触发的时间
val.it_value.tv_usec = 0;
val.it_value.tv_sec = 3;//第三秒开始发信号
//循环周期
val.it_value.tv_usec = 0;
val.it_value.tv_sec = 1;//后续每隔一秒发一次信号
setitimer(ITIMER_REAL,&val,NULL);
*/
while(1)//保证子进程处于运行状态
{
//睡眠做法
sleep(3);
dowork();
}
}
return 0;
}