守护进程:
守护进程也叫精灵进程,是Linux中的后台服务进,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事情。一般采用以d结尾的名字。
Linux后台的一些系统服务进程,没有控制终端,不能直接和用户交互。不受用户登录,注销的影响,一直运行着,他们都是守护进程。
特点:
- Linux后台服务进程
- 独立于控制终端
- 周期性地执行某种任务
- 不受用户登录和注销的影响
- 一般采用以d结尾的名字
进程组:
一个进程组由一个或多个进程祖成,每一个进程都有进程组。默认子进程与父进程属于同一个进程组。
进程组ID=进程组长(父进程)ID,只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关。
进程组的生存期:从进程组创建到最后一个进程离开。
会话:
- 一个会话是一个或多个进程组的集合。
- 创建会话的进程不能是进程组组长
- 创建会话的进程会成为一个进程组的组长进程,同时也会成为会话的会长。
- 新创建的会话丢弃原来的控制终端
- 创建新会话时,先fork创建子进程,子进程调用setsid函数
创建守护进程:
第一步:fork子进程,父进程退出
子进程继承了父进程的进程组ID,但具有一个新的进程ID(子进程本身的ID),这样保证了子进程不是一个进程组的组长ID,这是创建会话的前提
第二步:子进程调用setsid函数创建新会话
调用后:
- 该进程成为新会话的首进程,是会话的会长
- 成为一个新进程组的组长进程,是进程组组长
- 不受终端的控制
第三步:改变当前目录chdir
第四步:重设文件掩码 mode&~umask
子进程会继承父进程的文件掩码
增加子进程程序操作的灵活性
umask(0000);
编写一个守护进程,每间隔2s获取一次获取一次系统时间,把这个时间写入磁盘文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
void sighandler(int signo)
{
int fd=open("mydemon.log",O_RDWR | O_CREAT | O_APPEND,0755);//
if(fd<0)
{
perror("open error");
return ;
}
// time_t time(time_t *tloc);
time_t tloc;//获取磁盘时间
time(&tloc);
//char *ctime(const time_t *timep);
char *p=ctime(&tloc);//转为char*类型
write(fd,p,strlen(p));//写入文件
close(fd);
return ;
}
int main()
{
pid_t pid=fork();
if(pid<0 || pid>0)//父进程退出
{
return -1;
}
setsid();//子进程设置会话
umask(0000);//重设掩码,默认掩码为0002
struct sigaction act;
act.sa_handler=sighandler;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGALRM,&act,NULL);//注册SIGALRM信号处理函数
struct itimerval value;
value.it_interval.tv_sec=2;
value.it_interval.tv_usec=0;
value.it_value.tv_sec=1;
value.it_value.tv_usec=0;
setitimer(ITIMER_REAL,&value,NULL);//设置循环发送SIGALRM信号
while(1)
{
sleep(1);//让子进程不退出
}
}
结果:
我们可以看到该守护进程组长ID和会长ID都是自己的ID
时间也成功打印出来 。