【发布时间】:2015-05-16 12:46:23
【问题描述】:
我正在尝试使用锁定文件创建单个实例守护程序,但 fcntl() 似乎没有按预期工作...
int creat_lock_file (char * pid_fn)
{
struct flock pid_lck = {F_WRLCK, SEEK_SET, 0, 0, 0 };
/* Open/Create pid file */
int pid_fd = open (pid_fn, O_CREAT | O_WRONLY, 0640);
if (pid_fd == -1)
{
syslog (LOG_ERR, "Unable to open PID file > [Errno: %s]", strerror(errno));
return -1;
}
/* Place write lock on pid file */
if (fcntl(pid_fd, F_SETLK, &pid_lck) == -1) {
/* Unhandled error ocured */
syslog (LOG_ERR, "Unhandled error ocured while locking PID file > [Errno: %s]", strerror(errno));
close (pid_fd);
return -1;
}
/* Write PID to lock file */
char pid_lock_buf[11];
sprintf (pid_lock_buf, "%ld\n", (long) getpid ());
write (pid_fd, pid_lock_buf, strlen (pid_lock_buf)+1);
return 0;
}
int get_lock_file_status (char * pid_fn)
{
struct flock pid_lck = {F_WRLCK, SEEK_SET, 0, 0, 0 };
/* Open/Create pid file */
int pid_fd = open (pid_fn, O_CREAT | O_WRONLY, 0640);
if (pid_fd == -1)
{
syslog (LOG_ERR, "Unable to open PID file > [Errno: %s]", strerror(errno));
return -1;
}
/* try locking pid file*/
if(fcntl(pid_fd, F_GETLK, &pid_lck) == -1)
{
if(errno == EAGAIN || errno == EACCES) /* file already locked, close fd and return -1 */
{
close (pid_fd);
return -1;
}
else /* Unhandled error ocured */
{
syslog (LOG_ERR, "Unhandled error ocured while locking PID file > [Errno: %s]", strerror(errno));
close (pid_fd);
return -1;
}
}
close (pid_fd);
return 0;
}
所以我调用get_lock_file_status 并在它返回-1 时退出以确保没有其他实例正在运行,而不是我做一些事情(fork chdir 等)并调用creat_lock_file 在成功创建一个 pid 文件后创建并锁定一个 pid 文件守护进程...
当编译和运行程序按预期运行时,运行会创建锁定文件并将 pid 写入其中,但是当第二个实例启动时,第二个实例只是打开同一个锁定文件并将它自己的 pid 写入其中!
我做错了什么? get_lock_file_status 中的第二个实例不应该返回 -1 吗?
【问题讨论】:
-
这似乎是错误的方法。对于编程文件锁,flock() 函数似乎是正确的方法,这个函数,在 linux 上,在 'man 2 flock' 或在:linux.die.net/man/2/flock> 中有详细说明
-
@user3629249:
fcntl(2)和F_SET/GET/LK很好,还有 POSIX,flock(2)不是(尽管它被广泛使用)。这两种方法有不同的行为w.r.t。锁定继承和其他一些东西。fcntl()可以在文件区域上设置锁,flock()不能。