守护进程

一.简介

我们常用的进程一般分为三类:<1>交互进程 <2>批处理进程<3>守护进程。守护进程(Daemon)是一种运行在后台的一种特殊的进程。指的是在UNIX或其他多任务操作系统中在后台执行的电脑程序,并不会接受电脑用户的直接操控。此类程序会被以进程的形式初始化。它常常在系统启动时开始运行,在系统关闭时终止。

在linux/linux中,每个系统与用户进行交流的界面成为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端被称为这些进程的控制终端,当控制终端被关闭的时候,相应的进程都会自动关闭。但是守护进程却能突破这种限制,它脱离于终端并且在后台运行,并且它脱离终端的目的是为了避免进程在运行的过程中的信息在任何终端中显示并且进程也不会被任何终端所产生的终端信息所打断。

二.守护进程原理

【1】查看守护进程
命令 ps axj

【2】原理:守护进程有三个最基本的特点:后台运行,独立于终端,完成一定的任务。
1.首先所谓的后台运行过程是一般是在图形界面或是终端不可见的;
2.而独立于终端是说它不和终端联系,运行之后一般不接受终端的输入也不向终端输出;
3.每一个守护进程的运行都是为了完成一定的任务而运行的,这些任务一般都是系统相关的任务。

除开这些特殊性以外,守护进程与普通进程基本上没有什么区别
因此,实际上编写守护进程,可以把一个普通进程按照上述的守护进程的特性改造成为守护进程

守护进程必须与其运行前的环境隔离开来。
这些环境包括未关闭的文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩码等。
这些环境通常是守护进程从执行它的父进程中继承下来的。

【3】守护进程相关的概念
进程组:每运行一个程序或是命令就会产生一个进程组,而每一个进程组有一个组长进程.
(和我们创建用户一样,每创建一个用户都会有一个用户组。)

进程组由进程组号(GID)标识,进程组号(GID)为组长进程PID,一般进程组的第一个进程是组长进程。多个进程进程组成我们的进程组。

会话:一次登录形成一个会话,一个会话可包含多个进程组(前台或后台), 但只能有一个前台进程组.多个进程组组成我们的会话。

控制终端:会话的首进程(session leader)打开一个终端之后, 该终端就成为该会话的控制终端
与控制终端建立连接的会话首进程称为控制进程,一个会话只能有一个控制终端。

三.守护进程的建立步骤

<1>创建子进程,父进程退出
这是创建守护进程的第一步。由于守护进程是脱离控制终端的,因此,完成第一步后就会在Shell终端里造成一程序已经运行完毕的假象。之后的所有工作都在子进程中完成,而用户在Shell终端里则可以执行其他命令,从而在形式上做到了与控制终端的脱离。在Linux中父进程先于子进程退出会造成子进程成为孤儿进程,而每当系统发现一个孤儿进程是,就会自动由1号进程(init)收养它,这样,原先的子进程就会变成init进程的子进程。

<2>在子进程中创建的新会话 [脱离控制终端]
Linux是一个多用户多任务系统,每个进程都有一个进程ID,同时每个进程还都属于某一个进程组,而每个进程组都有一个组长进程,组长进程的标识ID等于进程组的ID,且该进程组ID不会因组长进程的退出而受到影响。会话期是一个或多个进程组的集合,通常,一个会话开始与用户登录,终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期。我们这里要用到setsid()函数。

setsid()函数的作用:创建一个新的会话,并且担任该会话组的组长。具体作用包括:让一个进程摆脱原会话的控制,让进程摆脱原进程的控制,让进程摆脱原控制终端的控制。

<3>改变进程的工作目录到"/"
使用fork创建的子进程继承了父进程的当前工作目录。守护进程不应当使用父进程的工作目录,应该设置自己的工作目录,通常可以通过chdir()来完成,一般可以将其设置为根目录

<4>重设文件掩码 umask(0)
守护进程从父进程继承来的文件创建方式掩码可能会拒绝设置某些许可权限,文件权限掩码是指屏蔽掉文件权限中的对应位。

<5>关掉不需要的文件描述符号 [0,1,2]==>标准输入、标准输出、标准出错。

创建流程图

四.相关代码实现

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

//1.创建子进程,父进程退出
//2.pid_t setsid(void);   创建一个新的回话,并把当前进程设置为进程组长
//3/chdir("/");
//4.umask(0)
//5.关闭不需要的文件描述符(标准输入,输出,出错)

int daemon_demo()
{
	pid_t pid = 0;
	int n = 0, i = 0;
	
	pid = fork();
	if(pid < 0){
		peror("Fail to fork");
	}else if (pid > 0){
		//1.创建子进程父进程退出,子进程友init进程收养。
		exit(EXIT_SUCCESS);
	}else if(pid == 0){
		//2.创建新的会话期,脱离当前终端的控制。
		if(setsid() < 0){
			perror("Fail to setsid");
			exit(EXIT_FAILURE);
		}
		//3.修改工作目录"/"为目录
		chdir("/");
		//4.重新设置文件掩码    ---umask()
		umask(0); //真正的权限  mode & ~umask
		//5.关闭需要使用的文件描述符close(0,1,2)
		close(0);
		close(1);
		close(2);
	}
}

int main(int argc, const char *argv[])
{
	int fd = 0;
	char *string = "hello world!\n"
	
	if(argc <2){
		fprintf(stderr, "Usage :%s argv[1]\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	
	fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0666);
	if(fd <0){
		perror("Fail to open");
		exit(EXIT_FAILURE);
	}	
	
	daemon_demo();
	
	while(1){
		//每隔1秒向文件中写入数据hello world
		write(fd, string, strlen(string));
		sleep(1)
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值