2015-09-22 64 views
1

Advanced Programming in the UNIX Environnement引用(页505),第13.6节:了解文件截断

我们需要截断该文件,因为 守护程序的上一个实例可能有一个进程ID比我们大,具有较大的 字符串长度。例如,如果守护程序 的先前实例是进程ID 12345,并且新实例是进程ID 9999,那么当我们 将进程ID写入文件时,我们将在 文件中留下99995。截断文件会阻止前一个守护进程 的数据显示为应用于当前守护进程。

这有人评论此功能:

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

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

感谢您的回答!

+1

的调用' ftruncate'在重写文件之前将文件长度重置为0,这样就不可能在文件的新版本中存在任何以前的内容(如果之前的内容大于新内容,可能会发生这种情况)。 –

+0

是的,但只有在您要覆盖现有文件时才有必要,并且新内容可能会比旧内容短。否则它是多余的(但无害)。 –

回答

4

在上面的例子中,文件最初是5个字节长。当您打开它进行写入,并且在不截断的情况下将字符串“9999”写入它时,它将仅覆盖前4个字节,并将第5个字节留在原地。因此该文件将读取“99995”。截断将文件长度设置为0,有效地删除以前的内容。

1

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

如果该文件已经存在,并且是一个普通文件和开放模式 允许写入(即是O_RDWR或O_WRONLY)也将被截断,以 长度为0