一、守护进程
1、守护进程的特点
- 后台服务进程
- 独立于控制终端【去掉依赖的终端】
- 周期性执行某任务
- 不受用户登录注销影响
- 一般采用以d结尾的名字(服务)
2、进程组
-
进程的组长?
组里面的第一进程
进程组的ID == 进程组的组长的ID【PID】 -
进程组组长的选则
进程中的第一个进程 -
进程组ID的设定
进程组的id就是组长的进程ID
3、会话 - 多个进程组
-
创建一个会话注意事项:
(1)不能是进程组长【其他进程才有机会创建会话】
(2)创建会话的进程成为新进程组的组长
(3)有些Linux版本需要root权限执行此操作(Ubuntu不需要)
(4)创建出的新会话会丢弃原有的控制终端
(5)一般步骤:先fork,父亲死,儿子执行创建会话操作(setsid) -
获取进程所属的会话ID
pid_t getpid(pid_t pid); -
创建一个会话
pid_t setsid(void);
4、创建守护进程模型
-
fork子进程,父进程退出【必须】
-
子进程创建新会话【必须】
setsid() -
改变当前工具目录chdir 【非必须】
可能出现的情况:插入一个U盘,a.out,在U盘目录中启动a.out
a.out启动过程中,U盘拔掉了
为了解决这种的情况 -
重设文件掩码【非必须】
子进程会继承父进程的掩码
增加子进程程序操作的灵活性
umask(0);//无任何的限制 -
关闭文件描述符【非必须】
释放资源
clse(0); close(1); close(2); -
执行核心工作【必须】
5、练习
写一个守护进程,每隔2s获取一次系统时间,将这个时间写入到磁盘文件
(1)创建守护进程
(2)需要一个定时器,2s触发一次
- settimer
- sleep
(3)信号捕捉
#include<fcntl.h>
#include<unistd.h>
#include<iostream>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/mman.h>
#include<signal.h>
#include<sys/time.h>
void dowork(int no)
{
time_t curtime;
//获取当前系统时间
time(&curtime);
//格式化时间
char* pt=ctime(&curtime);
//将时间写入文件
int fd=open("/home/linux123/temp++++.txt",O_CREAT|O_WRONLY|O_APPEND,0664);
write(fd,pt,strlen(pt)+1);
close(fd);
}
int main(int argc,const char* argv[])
{
pid_t pid=fork();
if(pid>0)
{
//父进程退出
exit(1);
}
else if(pid==0)
{
//变成会长 - 脱离终端控制
setsid();
//改变进程的工作目录
chdir("/home");
//重置文件掩码
umask(0);
//关闭文件描述符
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
//执行核心操作
//注册捕捉信号,在信号发出来之前进行捕捉,否则信号发完,还没注册成功
//signal();
struct sigaction act;
act.sa_flags=0;
act.sa_handler=dowork;
sigemptyset(&act.sa_mask);
sigaction(SIGALRM,&act,NULL);
//创建定时器
struct itimerval val;
//第一次触发的时间
val.it_value.tv_usec=0;
val.it_value.tv_sec=2;
//循环周期
val.it_interval.tv_usec=0;
val.it_interval.tv_sec=2;
setitimer(ITIMER_REAL,&val,NULL);
//保证子进程处于运行状态
while(1);
}
return 0;
}