了解文件截断

Understanding File Truncation

引自 Advanced Programming in the UNIX Environnement(第 505 页),第 13.6 节:

We need to truncate the file, because the previous instance of the daemon might have had a process ID larger than ours, with a larger string length. For examples , if the previous instance of the daemon was process ID 12345, and the new instance is process ID 9999, when we write the process ID to the file, we will be left with 99995 in the file. Truncating the file prevents data from the previous daemon appearing as if it applies to the current daemon.

这条评论是关于这个功能的:

already_running(void)
{
    int fd;
    char buf[16];
    fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE);
    if (fd < 0) {
        syslog(LOG_ERR, "can't open %s: %s", LOCKFILE, strerror(errno));
        exit(1);
    }
    if (lockfile(fd) < 0) {
        if (errno == EACCES || errno == EAGAIN) {
            close(fd);
            return(1);
        }
        syslog(LOG_ERR, "can't lock %s: %s", LOCKFILE, strerror(errno));
        exit(1);
    }
    ftruncate(fd, 0);
    sprintf(buf, "%ld", (long)getpid()); 
    write(fd, buf, strlen(buf)+1);
    return 0;
}

我不明白这种行为是如何发生的,以及文件截断是如何防止这种行为发生的。有人可以解释一下吗?

感谢您的回答!

在上面的示例中,文件的初始长度为 5 个字节。当您打开它进行写入,并在不截断的情况下向其中写入字符串“9999”时,它只会覆盖前 4 个字节,而保留第 5 个字节。因此该文件将显示为“99995”。截断将文件长度设置为 0,有效地删除了以前的内容。

Hellmar 已经提供了您问题的答案——但为了缩短代码(谁不喜欢代码高尔夫?),您可以将公开调用简化为:

already_running(void)
{
    int fd;
    char buf[16];
    fd = open(LOCKFILE, O_RDWR|O_CREAT|O_TRUNC, LOCKMODE);
    ...

在标志中添加O_TRUNC将导致文件被截断。 http://linux.die.net/man/2/open

If the file already exists and is a regular file and the open mode allows writing (i.e., is O_RDWR or O_WRONLY) it will be truncated to length 0.