C守护进程睡眠()

时间:2010-08-31 21:45:15

标签: c daemon sleep

我正在用c ++运行一个简单的守护进程测试。它运行正常没有睡眠()但如果我添加sleep()func它运行一次然后保持睡眠。此外,第一次运行应该在logs / log.dat文件中打印一次“Hello”,但这也不会发生。这是代码:

 #include <cstdlib>  
 #include <cstdio>  
 #include <iostream>  
 #include <unistd.h>  
 using namespace std;  
 int main(int argc, char** argv) {  
    FILE *f = NULL;   
    if ((f = fopen("logs/log.dat  ", "w")) != NULL) {  
        if (daemon(0, 0) >= 0) {  
            while (true) {  
                fprintf(f, "%s\n", "Hello");  
                sleep(5);  
            }  
        } else {  
            fprintf(f, "%s\n", "Error detaching terminal");  
        }  
    } else {  
        printf("%s\n", "Cannot open log file");  
    }  
    return 0;  
}

3 个答案:

答案 0 :(得分:5)

尝试在fprintf()之后添加fflush()。它可能正在工作,但尚未将数据写入磁盘。

答案 1 :(得分:3)

daemon()功能中有什么?特别是它是否关闭标准输入,标准输出和标准错误以外的打开文件?如果是这样,则后续fprintf()语句将失败,因为之后调用daemon()之前打开的文件将被关闭。

如果你的代码测试了打印函数的返回值,你就可以找到它(虽然你可能不得不打开一个带有绝对路径名的日志文件,以便能够从守护进程中报告它)

检查此假设的最快方法可能是在守护进程后打开日志文件。

请注意,某些daemon()例程也会更改目录 - 通常更改为根目录。这会让您对日志文件的相对路径感到头疼。


在MacOS X上,daemon(3)函数在<stdlib.h>中提供了声明;它是在BSD 4.4中引入的,似乎是:

  

概要

#include <stdlib.h>

 int
 daemon(int nochdir, int noclose);
     

描述

     

守护进程()函数用于希望从控制终端分离的程序        作为系统守护进程在后台运行。 [...]

     

除非参数nochdir非零,否则daemon()会将当前工作目录更改为根目录(/)。

     

除非参数noclose为非零,否则daemon()会将标准输入,标准输出和标准错误重定向到/ dev / null。


您可以检查FreeBSD 8源代码。

由于对daemon()的调用两次传递0,因此代码执行chdir("/")并将文件描述符0,1,2重新连接到'/ dev / null'。手册页继续讨论fork(2)setsid(2)。因此,我们可以确信您的程序将其标准I / O通道重新连接到/ dev / null,并将当前目录更改为根目录。

手册页确实提到您应该小心确保所有打开的文件都具有大于2的文件描述符以避免问题。你可以在某处打印'fileno(f)' - 它是一个整数 - 并确保它大于2.如果它不够大,那么这就是你的麻烦的原因;不要使用任何stdin,stdout或stderr已经关闭的程序来调用你的程序。

这还没有解释文件中缺少数据,也没有解释为什么sleep()会影响结果。当然,sleep()的经典实现提示信号和SIGALRM; daemon(3)的手册页提到了SIGHUP。但是,sleep(3)的FreeBSD 8实现使用nanosleep(2)系统调用。

所以,我将同意Jay的建议 - 文件将被完全缓冲,你必须等待大量的5秒周期来打印足够的数据来刷新缓冲区(可能需要4096字节,每5秒6个字节,将需要大约一个小时来生成文件中的任何内容)。添加fflush()最有可能解决“消息不出现”问题。或者,使用setvbuf(f, 0, _IONBF, 0);关闭所有缓冲,或使用setvbuf(f, 0, _IOLBF, BUFSIZ);启用线缓冲。 sleep()是一个因素,因为它会大大减慢处理速度。

答案 2 :(得分:0)

我有类似的问题,但因为我使用了syslog,所以使用fflush()是不可能的。 在我的情况下,解决方案是更改调试消息。

自:

syslog(LOG_DEBUG, "DEBUG: tick");

要:

syslog(LOG_DEBUG, "DEBUG: tick %d", i); // i is increased in the loop

所以每次都有不同的消息。