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触发一次
settimersleep(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; }