linux学习笔记13-守护进程
创建守护进程规则
- 父进程执行fork,执行exit让父进程退出.
- 在子进程中调用setsid.
- 让系统根目录成为子进程的工作目录.
- 把子进程的umask设置为0
- 关闭不需要的文件描述符.
守护进程简单上手
#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