C 守护进程 sleep()

发布于 2024-09-16 23:14:01 字数 758 浏览 7 评论 0原文

我正在 C++ 中运行一个简单的守护进程测试。它在没有 sleep() 的情况下运行良好,但如果我添加 sleep() 函数,它会运行一次然后保持睡眠状态。此外,第一次运行应该在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;  
}

I'm running a running a simple daemon test in c++. It runs fine without the sleep() but if I add sleep() func it runs once then stays a sleep. Further the first run should print once "Hello" in logs/log.dat file but that doesn't happen either. Here is the code:

 #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;  
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

笑饮青盏花 2024-09-23 23:14:01

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

Try adding fflush() after your fprintf(). It might be working but just has not written the data to the disk yet.

夜吻♂芭芘 2024-09-23 23:14:01

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

如果您的代码测试了打印函数的返回值,您将能够找到这一点(尽管您可能必须打开具有绝对路径名的日志文件才能从守护进程中报告它)。

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

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


在 MacOS X 上,daemon(3) 函数在 中提供声明;它是在 BSD 4.4 中引入的,看起来:

概要

#include ;

 整数
 守护进程(int nochdir,int noclose);

描述

daemon() 函数适用于希望将自己与控制终端分离并
作为系统守护进程在后台运行。 [...]

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

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


您可以检查 FreeBSD 8 源代码。

由于对 daemon() 的调用两次传递 0,因此代码确实执行了 chdir("/") 并将文件描述符 0、1、2 重新连接到 '/dev /无效的'。手册页继续讨论 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 字节,在 6 字节每 5 秒,大约需要一个小时才能生成文件中的任何内容)。添加 fflush() 最有可能解决“消息不出现”问题。或者,使用 setvbuf(f, 0, _IONBF, 0); 关闭所有缓冲,或使用 setvbuf(f, 0, _IOLBF, BUFSIZ); 启用行缓冲。而 sleep() 是一个因素,因为它大大减慢了处理速度。

What is in the daemon() function? In particular, does it close open files other than standard input, standard output and standard error? If so, then the subsequent fprintf() statements fail because the file that was opened before you called daemon() is closed afterwards.

If your code tested the return values from the printing functions, you would be able to find this out (though you'd probably have to open a log file with an absolute pathname to be able to report it from the daemonized process).

The quickest way to check this hypothesis may be to open the log file after daemonizing.

Note that some daemon() routines change directory too - typically to the root directory. That would give you a headache with the relative path to the log file.


On MacOS X, the daemon(3) function is provided with a declaration in <stdlib.h>; it was introduced in BSD 4.4, it seems:

SYNOPSIS

#include <stdlib.h>

 int
 daemon(int nochdir, int noclose);

DESCRIPTION

The daemon() function is for programs wishing to detach themselves from the controlling terminal and
run in the background as system daemons. [...]

Unless the argument nochdir is non-zero, daemon() changes the current working directory to the root (/).

Unless the argument noclose is non-zero, daemon() will redirect standard input, standard output, and standard error to /dev/null.


You can inspect the FreeBSD 8 source code.

Since the call to daemon() passes 0 twice, the code does do a chdir("/") and it reconnects file descriptors 0, 1, 2 to '/dev/null'. The manual page goes on to discuss fork(2) and setsid(2). So, we can be moderately confident that your program has its standard I/O channels reconnected to /dev/null, and the current directory changed to the root directory.

The man page does mention that you should be careful to ensure that any opened files have a file descriptor greater than 2 to avoid issues. Can you print 'fileno(f)' somewhere - it is an integer - and ensure that it is greater than 2. If it is not big enough, then that is the cause of your trouble; don't invoke your program with any of stdin, stdout or stderr already closed.

That doesn't yet explain the absence of data from the file, nor why sleep() affects the result. Of course, the classic implementation of sleep() fiddles with signals and SIGALRM; the man page for daemon(3) mentions SIGHUP. However, the FreeBSD 8 implementation of sleep(3) uses the nanosleep(2) system call.

So, I'm going to agree with Jay's suggestion - the file will be fully buffered and you have to wait for a large number of 5-second cycles to print enough data to flush the buffer (that might need 4096 bytes, at 6 bytes per 5 seconds, will require about an hour to produce anything in the file). Adding fflush() is most likely to fix the 'non-appearance of message' issue. Alternatively, use setvbuf(f, 0, _IONBF, 0); to turn off all buffering, or setvbuf(f, 0, _IOLBF, BUFSIZ); to enable line buffering. And sleep() is a factor simply because it slows the processing down so much.

淡墨 2024-09-23 23:14:01

我遇到了类似的问题,但因为我使用了 syslog,所以不可能使用 fflush() 。
就我而言,解决方案是更改调试消息。

发件人:

syslog(LOG_DEBUG, "DEBUG: tick");

收件人:

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

这样每次都会有不同的消息。

I had a similar problem, but because I used syslog, using fflush() wasn't possible.
In my case the solution was to change debug message.

From:

syslog(LOG_DEBUG, "DEBUG: tick");

To:

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

So that there was every time different message.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文