Linux守护进程和会话

守护进程:

守护进程也叫精灵进程,是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

时间也成功打印出来 。

缺点:每发送一次SIGALRM信号都要打开一次文件,反复进入内核区,我们可以通过以下操作改善:

#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>
int flag=1;//定义一个全局开关变量
int fd;
void sighandler(int signo)
{

	// time_t time(time_t *tloc);
	time_t tloc;
	time(&tloc);
	//char *ctime(const time_t *timep);
	char *p=ctime(&tloc);
	if(flag==1)
	{
		fd=open("mydemon.log",O_RDWR | O_CREAT | O_APPEND,0755);
		if(fd<0)
		{
			perror("open error");
			return ;
		}
		flag=0;//开关关闭,下一个SIGALRM不再打开文件,直接写入
	}
	write(fd,p,strlen(p));
	return ;
}
int main()
{
	pid_t pid=fork();
	if(pid<0 || pid>0)
	{
		return -1;
	}
	setsid();

	umask(0000);

	struct sigaction act;
	act.sa_handler=sighandler;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	sigaction(SIGALRM,&act,NULL);

	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);
	int size;
	int i=1;
	while(1)
	{
		size=lseek(fd,SEEK_END,0);
		if(size>100)//文件大小超过100就重新创建一个文件
		{
			for(;i<100;i++)
			{
				rename("mydemon.log","mydemon.log.bak[i]");
				flag=1;
			}
		}
		sleep(1);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落落落sss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值