守护进程的创建

1.守护进程的概念

守护进程是指在后台运行的,没有控制终端与之相连的进程,它独立于控制终端,周期性的执行某种任务.

2.守护进程的启动

  • 在linux系统启动时从启动脚本/etc/rc.d中启动.
  • 可以由作业规划进程crond 启动.
  • 可以由用户终端(通常是shell)执行;

3.守护进程创建的要点

  • 让进程在后台执行,方法是fork一个子进程,然后使得父进程退出,
  • 调用setsid创建一个新对话时期,控制终端,登录回话和进程组通常是从父进程继承下来的,守护进程要摆脱它们,不受它们的影响,其方法是调用setsid使进程成为一个回话组长.注意:当进程是会话组长时,调用setsid会失败,但第一点已经保证进程不是会话组长,setsid 调用成功后,进程成为新的会话组长和进程组长,并与原来的登录会话和进程组脱离,由于会话过程队控制终端的独占性,进程同时与控制终端脱离.
  • 禁止进程重新打开控制终端,经过以上步骤,进程已经成为了一个无终端的会话组长,但会话组长可以重新申请打开一个终端,为了避免这种情况的发生,再一次调用 fork()创建新的子进程,使调用fork的进程退出.
  • 关闭不再需要的文件描述符.创建的子进程会继承父进程打开的文件描述符,不关闭,将会系统资源浪费,先得到最高的文件描述符,然后用一个循环程序,关闭0到最高文件描述符值的所有文件描述符,
  • 将当前目录更改为根目录,当守护进程当前工作目录在一个装配文件系统中,该文件系统不会被拆卸,一般需要将工作目录改为根目录;
  • 将问文件创建时使用的屏蔽字设置为0,进程从父进程那里继承的文件创建屏蔽子可能会拒绝某些许可权,所以将unask(0)将屏蔽字清0;
  • 处理 SIGCHLD信号,这一步不是必须的,但对于某些数据,特别是服务器进程往往在请求到来时生成的子进程处理请求,如果父进程不等待子进程结束,子进程将成为僵尸进程,从而占用系统资源,如果父进程等待子进程结束,将增加父进程的负担.在linux下简单的将SIGCHLD信号的操作设为SIG_IGN,这样,子进程结束不会产生僵尸进程;
/*创建一个守护进程*/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
#include <syslog.h>
int init_daemon(void)
{
	int pid;
	int i;
	/*忽略终端I/O信号,STOP信号*/
	signal(SIGTTOU,SIG_IGN);
	signal(SIGTTIN,SIG_IGN);
	signal(SIGTSTP,SIG_IGN);
	signal(SIGHUP,SIG_IGN);

	pid=fork();
	if(pid > 0)
	{
		exit(0);//结束父进程,使得子进程成为后台进程
	}
	  else if(pid<0)
	{
    		return -1;
	}
	//建立一个新的进程组,在这个进程组中,子进程成为这个进程的首进程,以使该进程脱离所有终端
	setsid();
	/*再次新建一个子进程,退出父进程,保证该进程不是进程组长,同时让该进程无法再打开一个新的终端*/
	pid=fork();
	if(pid>0)
	{
		exit(0);
	}
	else if(pid<0)
	{
		return -1;
	}
	/*关闭所有从父进程继承的不在需要的文件描述符*/
	for(i=0;i<NOFILE;close(i++))
	/*改变工作目录,使得进程不与任何文件系统联系*/
	chdir("/");
	/*将文件屏蔽字设置为0*/
	umask(0);
	/*忽略SIGCHLD*/
	signal(SIGCHLD,SIG_IGN);
	return 0;
}
int main()
{
	time_t now;
	init_daemon();
	syslog(LOG_USER|LOG_INFO,"测试守护进程!\n");
	while(1)
	{
		sleep(1);
		time(&now);
		syslog(LOG_USER | LOG_INFO,"系统时间:\t%s\t\t\n",ctime(&now));
	}
}

 3.进程退出

1.正常退出

  • 在main函数中执行return.
  • 调用 exit(int exit  code)函数:参数int exit code为0,代表进程正常终止,若为其它值代表程序执行过程中有错误发生;在头文件<stdio.h>中申明;而_exit()在头文件<unistd.h>;

2.异常退出

  • 调用about函数
  • 进程过程中收到某个信号,而该信号使程序终止;

   

你可能感兴趣的:(守护进程的创建)