(1)任何一个进程都可以将自己变成守护进程。
(2)create_daemon函数要素
最初的daemon_2016-10-14.c
#include
#include
#include
void create_daemon(void);
int main(void)
{
create_daemon();
while(1){
printf("I am running.\n");
sleep(1);
}
return 0;
}
//函数作用就是把调用该函数的进程变成一个守护进程
void create_daemon(void)
{
}
执行a.out后,屏幕输出”I am running.”。
在执行a.out的同时,ps -ajx
后,可以发现进程2536。但在停止执行a.out后,进程2536也没有了。
现在开始写create_daemon()函数。
//函数作用就是把调用该函数的进程变成一个守护进程
void create_daemon(void)
{
pid_t pid;
if((pid = fork()) < 0)
{
perror("fork");
exit(-1);
}
else if(pid > 0)
{
/* 父进程退出 */
exit(0);
}
/* 子进程 */
/* setsid将当前进程设置为一个新的会话期session */
/* 目的就是让当前进程脱离控制台 */
pid = setsid();
if(pid < 0)
{
perror("setsid");
exit(-1);
}
/* 将当前进程的工作目录设置为根目录 */
chdir("/");
/* umask设置为0,确保将来进程有最大打文件权限 */
umask(0);
/* 关闭所有文件描述符号 */
/* 先要获取当前系统中所允许打开的最大文件数目 */
int i;
int cnt = sysconf(_SC_OPEN_MAX);
for(i = 0; i < cnt; i++)
{
close(i);
}
/* 把标准输入、标准输出、标准错误输出定位到/dev/null */
open("/dev/null", O_RDWR);
open("/dev/null", O_RDWR);
open("/dev/null", O_RDWR);
}
执行a.out,但发现并未输出。
但是ps -ajx
还是可以看到a.out确实在执行。进程5291。
现在a.out就已经是守护进程了,此时就算我把执行a.out的终端关掉,但是ps -ajx
还是能看见a.out进程,要关闭进程只能kill -9 进程号
。
因为已经将标准输入、标准输出、标准错误输出定向到/dev/null,所以守护进程不能向控制台输出信息,而且守护进程已经脱离了控制台。那么守护进程如何向用户输出信息?我们可以使用syslog来记录调试信息。
#include
void openlog(const char *ident, int option, int facility);
/* syslog记录一条信息 */
void syslog(int priority, const char *format, ...);
void closelog(void);
ident是识别字符串,一般设置为当前应用程序的名字。
option:
facility可以理解为日志的来源或设备或选择条件,目前常用的facility有以下几种:
priority(log level)日志优先级的级别,一般分为以下几种级别(从低到高:
#include
#include
#include
int main(void)
{
openlog("syslogTest.out", LOG_PID| LOG_CONS, LOG_USER);
syslog(LOG_INFO, "this is my log info");
syslog(LOG_INFO, "this is another log info");
closelog();
return 0;
}
(1)操作系统中有一个守护进程syslogd(开机运行,关机时才结束),这个守护进程syslogd负责进行日志文件的写入和维护。
(2)syslogd是独立于我们任意一个进程运行的。我们当前进程和syslogd进程本来是没有任何关系的,但是我们当前进程可以同通过调用openlog打开一个和syslogd相连接的通道,然后通过syslog向syslogd发消息,然后由syslogd来将其写入到日志文件系统中。
(3)syslogd其实就是一个日志文件系统的服务器进程,提供日志服务。任何需要写入日志的进程都可以通过openlog/syslog/closelog这三个函数来利用syslogd提供的日志服务。这就是操作系统的服务式的设计。