【问题标题】:fopen() seems not work when I create a daemon process当我创建一个守护进程时 fopen() 似乎不起作用
【发布时间】:2026-02-09 04:50:01
【问题描述】:

这是我的主要源代码:

int main(int argc, char *argv[]) {
    [...]

    if (become_daemon(0) == -1) {
        exit(EXIT_FAILURE);
    }

    while (main_loop == LOOP_CONTINUE) {
        [...]

        if (log_data(date_temp, data_processed) < 0) {
            [...]
        } else {
            [...]
        }
        sleep(measure_rate);
    }
    [...]
}

这里是我的函数定义:

int become_daemon(int flags) {
    int maxfd, fd;

    switch (fork()) {
      case -1:
        return -1;
      case 0:
        break;
      default:
        exit(EXIT_SUCCESS);
    }

    if (setsid() == -1)
        return -1;

    switch (fork()) {
      case -1:
        return -1;
      case 0:
        break;
      default:
        exit(EXIT_SUCCESS);
    }

    if (!(flags & BD_NO_MASK0))
        umask(0);

    if (!(flags & BD_NO_CHDIR))
        chdir("/");

    if (!(flags & BD_NO_CLOSE_FILE)) {
        maxfd = sysconf(_SC_OPEN_MAX);
        if (maxfd == -1)
            maxfd = BD_MAX_CLOSE;

        for (fd = 0; fd < maxfd; fd++)
            close(fd);
    }

    if (!(flags & BD_NO_REOPEN_STD_FDS)) {
        close(STDIN_FILENO);

        fd = open("/dev/null", O_RDWR);

        if (fd != STDIN_FILENO)
            return -1;
        if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO)
            return -1;
        if (dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
            return -1;
    }
    return 0;
}

int log_data(char *date, double array_data[DATA_NUM]) {
    FILE *file;

    if ((file = fopen(DATALOG_FILE, "a")) == NULL)
        return -1;

    fprintf(file, "%s ; %.2f ; %.2f ; %.2f ; %.2f ; %.2f ; %.2f\n",
            date, array_data[0], array_data[1], array_data[2],
            array_data[3], array_data[4], array_data[5]);

    fclose(file);

    return 0;
}

这是我的问题:

当我在激活become_daemon() 函数的情况下编译我的代码然后我执行程序时,文件DATALOG_FILE(它是"xxxxxx.txt" 的定义)并没有被创建。如果我在没有become_daemon() 函数调用的情况下进行编译,则程序可以正常工作并创建文件。

我什至注意到,如果我添加该行

sudo /my/folder/program

rc.local 在启动时运行它,它会像我想要的那样启动,但即使在这种情况下,它也不会创建文件 DATALOG_FILE。

我是守护进程的新手,谁能告诉我这种行为的原因?

【问题讨论】:

  • become_daemon 将 cwd 更改为 /,这可能是问题吗?由于 DATALOG_FILE 似乎是相对路径...
  • 当然,您可以进一步缩小问题范围,而不是创建文件。 为什么没有创建? fopen 调用是否失败? become_daemon 调用是否失败?还有什么?一旦您发现哪个呼叫失败,您就可以获得errno 以进一步缩小原因。在寻求帮助之前应该很容易进一步挖掘。
  • chdir("/") 中的become_daemon() 表示守护程序尝试(并且可能失败)在根目录中创建文件。指定文件的绝对路径名,而不是相对名称。或者决定chdir("/") 是否合理。有理由这样做;有时,有理由将目录更改到其他位置,有时(尽管不那么频繁)有理由根本不更改目录。

标签: c process fopen daemon


【解决方案1】:

正如 Ctx 在他的评论中提到的,函数become_daemon 可能会将当前目录更改为/。如果DATALOG_FILE 是一个相对文件名,例如您在问题中写的"xxxxxx.txt",则守护进程将无法在系统根目录中创建它,除非它具有root 权限。

不要通过将BD_NO_CHDIR 作为参数传递给become_daemon 来更改当前目录,或者将DATALOG_FILE 设为绝对路径。

【讨论】:

  • 感谢您的回复,它解决了我与守护进程相关的问题。但是rc.local 呢?如果我添加行/my/folder/program 以在启动时启动它,它似乎再次更改了/ 中的目录。你能解释一下为什么吗?
  • @thoraz:它不会更改目录,而是以/作为当前目录开始。