linux学习笔记13-守护进程

创建守护进程规则

  1. 父进程执行fork,执行exit让父进程退出.
  2. 在子进程中调用setsid.
  3. 让系统根目录成为子进程的工作目录.
  4. 把子进程的umask设置为0
  5. 关闭不需要的文件描述符.

守护进程简单上手

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <syslog.h>

int main(int argc,char *argv[])
{
	//1 fork  
	pid_t pid = fork();
	if(pid < 0)
	{
		return -1;
	}
	if(pid > 0)
	{
		exit(0);   //1.1 让父进程退出
	}
	else
	{
		setsid();   //2 setsid 设置一个新的会话
		chdir("/"); //3 设置根目录为当前程序的工作目录
		umask(0);   //4 设置umask为0
		close(STDIN_FILENO); //5 关闭文件描述符
		close(STDOUT_FILENO);
		close(STDERR_FILENO);
		syslog(LOG_INFO,"daemon process is running!");  //记录到系统日志中
		while(1) //这里只是为了模拟,不让程序退出
		{
			sleep(1);
		}
	}
	return 0;
}

查看输出(不同发行版本可能不一样这里centos) cat /var/messages


真正应该写

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <signal.h>
#include <syslog.h>

//用sigaction替代signal函数的功能
int mysignal(int signo,void (*func)(int))
{
	struct sigaction act,oact;
	act.sa_handler = func;
	sigemptyset(&act.sa_mask); //必须用sigemptyset初始化sigcation的sa_mask成员
	act.sa_flags = 0;
	return sigaction(signo,&act,&oact);
}

//信号触发处理动作的函数
void signal_handler(int signo)
{	
	switch(signo)
	{
 	   case SIGUSR1:
		syslog(LOG_INFO,"user signal!\n");	//需要cat /var/log/message进行查看        
	   	exit(1);
		break;
	}
}

int mydaemon()
{
   pid_t pid = fork();  //1 fork
   if(pid < 0)
   {
   	return -1;
   }
   if(pid > 0)
   {
   	exit(0);        //1.1 让父进程退出
   }
   else
   {
   	setsid();       //2 setsid 设置一个新的会话
	chdir("/");     //3 设置当前程序的工作目录为根目录
	umask(0);       //4 设置umask为0
	close(STDIN_FILENO); //5.关闭输入等文件描述符
	close(STDOUT_FILENO);
	close(STDERR_FILENO);
	return 1;
   }
}

int main(int argc,char *argv[])
{	
        int daemon_result = mydaemon();
	if(daemon_result == -1)
	{
	   return -1;
	}
	mysignal(SIGUSR1,signal_handler);	
	while(1)
	{
		printf("wait alarm!\n");   //这里的输出是不会在终端上显示,因为在mydaemon中,已经关闭输出的文件描述符
		sleep(5);
	}
	return 0;
}

如何保证守护进程是单实例的呢? 用shell

#!/bin/sh

WHOAMI=`whoami`

PID=`ps -u $WHOAMI | grep sigusr1_daemod | awk '{print $1'}`

if (test "$PID" = "") then
	./sigusr1_daemod
fi

关闭守护进程的shell

#!/bin/sh

WHOAMI=`whoami`

PID=`ps -u $WHOAMI | grep sigusr1_daemod | awk '{print $1'}`

if (test "$PID" != "") then
	kill -s 2 $PID
fi


秋风 2017-01-09