写文件,st_mtime不会改变

时间:2012-01-05 20:45:30

标签: c++ c linux posix

我有一个程序要检查文件是否已被修改。 regtest失败,事实上,尽管文件已经更改,但st_mtime还没有!此外,外部统计也证实了这一点。

我相信st_mtime 更改,因为stat(2)表示

  

字段st_mtime由文件修改更改,例如,mknod(2),truncate(2),utime(2)和write(2)(大于零字节)。

这里有一些C代码说明了这个问题:

#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


void touch(const char *fn, const char *contents)
{
    FILE *fp;
    assert(fp = fopen(fn, "w"));
    fprintf(fp, contents);
    fclose(fp);
}


int main( int argc, char *argv[] )
{
    struct stat st;
    char path[] = "/tmp/foo";
    time_t m1, m2;
    unsigned int t;

    touch(path, "hello\n");
    assert(!stat(path, &st));
    m1 = st.st_mtime;

    touch(path, "hello, world!\n");
    t = sleep(2);
    assert(!stat(path, &st));
    m2 = st.st_mtime;

    printf("Sleep remaining: %lu\n", t);
    printf("Elapsed modtime=%lu\n", m2 - m1);
}

这是为bash提供的东西,以确认它不仅仅是在C程序中缓存:

  

$ while true;做stat / tmp / foo | grep修改;睡1;完成

有什么建议吗? Fwiw,这是在如此确定的系统上运行的:

jeff@london:src $ uname -a
Linux london 2.6.32-37-generic #81-Ubuntu SMP Fri Dec 2 20:32:42 UTC 2011 x86_64 GNU/Linux
jeff@london:src $ 

2 个答案:

答案 0 :(得分:4)

首先,我强烈建议您不要在assert内使用带副作用的陈述。我理解它很方便,如果代码永远不会生产,那真的不重要,但它不是好形式。特别是,如果您定义NDEBUGassert将转换为noop,则不会执行条件的代码。

现在,问题很可能是您在sleep次调用之后调用touch调用,而不是在它们之间。改变这个:

touch(path, "hello\n");
assert(!stat(path, &st));
m1 = st.st_mtime;

touch(path, "hello, world!\n");
t = sleep(2);
assert(!stat(path, &st));
m2 = st.st_mtime;

touch(path, "hello\n");
int rv = stat(path, &st);
assert(!rv);
m1 = st.st_mtime;

t = sleep(2);

touch(path, "hello, world!\n");
int rv = stat(path, &st);
assert(!rv);
m2 = st.st_mtime;

答案 1 :(得分:1)

永远不要在有副作用的函数上使用assert

始终这样做:

FILE * fp;
fp = fopen(...);

assert(fp != NULL);

包含assert()的整行从发布版本中消失。