浅谈守护进程


一、守护进程是什么?

定义:脱离于终后台服务程序端,在后台独立运行的程序;
特点

  • 独立控制终端,用户不需要和终端交互;
  • 周期性的执行某任务;
  • 不受用户登录注销的影响;
  • 一般采用d结尾的名字(服务)

了解了守护进程的基本概念之后,还需要了解两个知识点:进程组会话

  1. 进程组
    一个或多个进程的集合;
    进程组ID作为唯一标识;
    组长进程是进程组的第一个进程;
    进程组的ID == 进程组的组长的ID;
  2. 会话
    会话是由多个进程组组成;
  3. 创建一个会话注意的事项
    *不能是组长进程;
    创建会话的进程成为新进程组的组长;
    创建的新会话会丢弃原有的控制终端;
    一般步骤:先fork(),父进程死,子进程创建会话(setsid());
    获取进程所属的会话ID
    pid_t setsid(pid_t pid);
    创建一个会话:
    pid_t setsid(void);

二、创建守护进程的过程

1.枯燥的概念

  1. 创建子进程,父进程退出;
  2. 子进程创建新的会话,调用setsid();
    setsid()函数的作用
  • 在上一步,调用fork()创建子进程,再将父进程退出;
  • 而在调用fork()时,子进程全盘拷贝了父进程的会话、进程组和控制终端,虽然父进程退出了,但是这些没有改变,因此还不是真正意义的独立开来;
  • 而setsid()可以使进程完全独立,从而摆脱其它进程的控制。
  1. 改变当前目录为根目录

  2. 重设文件权限掩码
    文件权限掩码是指屏蔽文件权限的对应位;
    比如,有一个文件的权限掩码是050,它就屏蔽了文件组的可读和可执行权限。

使用fork()新建的子进程继承了父进程的文件权限掩码,这会给子进程使用文件带来很多麻烦,因此把文件权限掩码设置为0 ,可以增强守护进程的灵活性,一般用umask(0);

  1. 关闭文件描述符
    与文件权限码一样,使用fork()创建的子进程会继承父进程的一些已经打开的文件,这些文件可能用于不会被守护进程读写,但是它们一直消耗系统资源。

在第2步之后,子进程即守护进程已经与所属终端断了联系;
因此,从终端输入的字符不可能到达守护进程,守护进程中用常规方法输出的字符也不可能在终端打印出来;
所以,文件描述符0(输入),1(输出),2(报错)已经失去了存在的价值,应该被关闭。

2.直观的代码

代码如下:

/*
	守护进程实例:每隔2s获取一次系统时间,写入到文本文件中;
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h>
#include <time.h>

void func(int no);  // callback function
int main(int argc, char **argv)
{
	pid_t pid = fork();
	if(pid >0)
	{
		printf("parent process exit\n");
		_exit(1);
	}
	else if(pid == 0)
	{
		setsid(); //child create session
		umask(0);
		
		close(STDIN_FILENO);   //close file descriptor
		close(STDOUT_FILENO);
		close(STDERR_FILENO);
		
		
		struct sigaction act;
        act.sa_flags = 0;
		act.sa_handler = func;
		sigaddset(&act.sa_mask, SIGQUIT);
		
		itimerval time;    //set timer
		time.it_value.tv_sec = 2;
		time.it_value.tv_usec = 0;
		time.it_interval.tv_sec = 1;
		time.it_interval.tv_usec = 0;
		
		sigaction(SIGVTALRM, &act, NULL);
		setitimer(ITIMER_VIRTUAL, &time, NULL);
 		
		while(true);
	}
	
	return 0;
}

void func(int no)
{
time_t currtime;
time(&currtime);
char* ptr = ctime(&currtime);


int fd = open("/home/fork/setsid.txt", O_CREAT | O_WRONLY | O_APPEND, 0777);
write(fd, ptr, sizeof(ptr)+1);
close(fd);

}
	

总结

这部分知识点有点枯燥啊,守护进程,孤儿进程,僵尸进程,继续努力,稍后再更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值