引自Advanced Programming in the UNIX Environnement
(page 505), Section 13.6:
我们需要截断文件,因为守护进程可能有一个比我们的进程ID大的进程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;
}
我不明白这种行为是如何可能的,以及文件截断如何防止这种行为发生。有人能解释一下吗?
谢谢你的回答!
在上面的例子中,文件最初是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
如果文件已经存在,并且是一个普通文件,并且打开模式允许写入(即,是O_RDWR或O_WRONLY),它将被截断为长度0。