Linux守护进程:
守护进程是运行在后台的一种特殊进程,它无需用户输入就能够运行,经常是提供某种服务。Linux的大多数服务器就是用守护进程实现的。
守护进程的步骤
1 首先执行fork后,让父进程退出。
2 在子进程中调用setsid,取消进程与任何控制终端的关联。
3 让根目录成为子进程的当前工作目录。 chdir('/')
4 设置进程的umask = 0(设置权限)。
5 关闭子进程继承的任何不必要的文件描述符。
1 一个daemon实例:让后台运行的daemon程序向屏幕打印信息
一旦系统调用setsid,它就不再有控制终端,所以也就无处发送正常情况下应该发往stdout或者stderr的输出。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include<signal.h>
#include <fcntl.h>
#include<errno.h>
//让后台运行的daemon程序向屏幕打印信息
//创建一个守护进程
//一个信号捕捉函数
//一个回调函数listenfifo (读管道)
void setdaemon()
{
int pid = fork();
if(pid == -1)
{
printf("create fork error\n");
}
if(pid == 0)
{
printf("child begin\n");
setsid();
chdir("/");
umask(0);
//close(STDIN_FILENO);
//close(STDOUT_FILENO);
//close(STDERR_FILENO);
}
if(pid > 0)
{
exit(0);
}
}
void catch_signal1(int sign)
{
switch(sign)
{
case SIGINT:
listenfifo();
break;
}
}
//创建一个读管道
void listenfifo()
{
int len = 0;
char buf[1024];
memset(buf,0,sizeof(buf));
int fd = open("/home/zxy/6/fifo1",O_RDONLY);
if(fd == -1)
{
printf("open fifo1 error\n");
}
len = read(fd,buf,sizeof(buf));
if(len > 0)
{
if(buf[strlen(buf) - 1] == '\n')
{
buf[strlen(buf) - 1] = 0;
}
close(STDOUT_FILENO);
open(buf,O_WRONLY);
}
close(fd);
}
int signal1(int signo,void(*func)(int))
{
struct sigaction act,oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
return sigaction(signo,&act,&oact);
}
int main(void)
{
setdaemon();
signal1(SIGINT,catch_signal1);
while(1)
{
printf("hello world\n");
sleep(1);
}
return EXIT_SUCCESS;
}
还有一个守护进程是后台服务程序,所以只需一个进程即可,但此时可以创建多个相同的守护进程,没有意义,所以解决此办法是使用shell脚本进行编程。
通过shell脚本编程实现只能建立一个守护进程,实现启动守护进程、结束守护进程。
#! /bin/sh #解释器
WHOAMI=`whoami`
PID=`ps -u $WHOAMI | grep /daemon | awk '{print $1}'`
if(test "$1" = "" ) then
echo "daemon [start] [stop] [version]"
exit 0
fi
if(test "$1" = "status" ) then
if(test "$PID" = "") then
echo "not run"
else
echo " run"
fi
exit 0
fi
if(test "$1" = "start") then
if(test "$PID" = "") then
./daemon
fi
exit 0
fi
if(test "$1" = "version") then
echo "version is 1.1.1"
exit 0
fi
if(test "$1" = "stop") then
if(test "$PID" = "") then
kill $PID
fi
echo "daemon [start] [stop] [version]"
2 使用fifo与守护进程通信,实例:
readfifo_daemon.c代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include<signal.h>
#include <fcntl.h>
#include<errno.h>
//使用fifo与守护进程通信
//先是创建守护进程
//建立读管道
void setdeamon()
{
int pid = fork();
if(pid == -1)
{
printf("ct=reate fork errror\n");
}
if(pid == 0)
{
setsid();
chdir("/");
umask(0);
}
if(pid > 0)
{
exit(0);
}
}
void readfifo()
{
int len = 0;
char buf[1024];
memset(buf,0,sizeof(buf));
int fd = open("/home/zxy/6/fifo1",O_RDONLY);//返回打开的文件描述符
if(fd == -1)
{
printf("open fifo error %s\n",strerror(errno));
return;
}
while((len = read(fd,buf,sizeof(buf))) > 0)
{
printf("%s\n",buf);
memset(buf,0,sizeof(buf));
}
close(fd);
return;
}
int main(void)
{
setdeamon();
readfifo();
return EXIT_SUCCESS;
}
writefifo_daemon.c代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include<signal.h>
#include <fcntl.h>
#include<errno.h>
//创建写管道
void writefifo()
{
int len = 0;
char buf[1024];
memset(buf,0,sizeof(buf));
int fd = open("/home/zxy/6/fifo1",O_WRONLY);
if(fd == -1)
{
printf("open fifo error %s\n",strerror(errno));
return ;
}
while(1)
{
scanf("%s",buf);
write(fd,buf,sizeof(buf));
memset(buf,0,sizeof(buf));
}
close(fd);
return;
}
int main()
{
writefifo();
return 0;
}