简体   繁体   English

fcntl如何知道哪个进程持有锁定文件?

[英]fcntl how to know which process hold lock file?

I'm new with fcntl locking and following this example to create a sample lock in linux using c code: http://www.informit.com/articles/article.aspx?p=23618&seqNum=4 我是fcntl锁定的新手,并按照以下示例使用c代码在linux中创建了示例锁定: http : //www.informit.com/articles/article.aspx? p=23618&seqNum =4

I wonder how can we can print out which process hold the lock file and which process is waiting for lock. 我想知道我们如何才能打印出哪个进程持有锁定文件以及哪个进程正在等待锁定。 I consider using l_pid to figure out the process id which is holding the lock but i'm not sure the right way to do it. 我考虑使用l_pid来找出持有锁的进程ID,但是我不确定这样做的正确方法。 What is the best way to print out which process is holding the lock? 打印出哪个进程持有锁的最佳方法是什么?

As the man 2 fcntl page describes, you can use the F_GETLK to obtain the process ID that has the conflicting lock (if the conflicting lock is a process-associated one). man 2 fcntl页所述,您可以使用F_GETLK获取具有冲突锁的进程ID(如果冲突锁是与进程相关的锁)。 So, for example, 因此,例如

/* Return 0 if descriptor locked exclusively, positive PID if
   a known process holds a conflicting lock, or -1 if the
   descriptor cannot be locked (and errno has the reason).
*/
static pid_t  lock_exclusively(const int fd)
{
    struct flock  lock;
    int           err = 0;

    if (fd == -1) {
        errno = EINVAL;
        return -1;
    }

    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;
    if (!fcntl(fd, F_SETLK, &lock))
        return 0;

    /* Remember the cause of the failure */
    err = errno;

    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;
    lock.l_pid = 0;
    if (fcntl(fd, F_GETLK, &lock) == 0 && lock.l_pid > 0)
        return lock.l_pid;

    errno = err;
    return -1;
}

Do note that fd must be open for reading and writing. 请注意,必须打开fd进行读写。 I recommend using open(path, O_RDWR | O_NOCTTY) or open(path, O_WRONLY | O_NOCTTY) . 我建议使用open(path, O_RDWR | O_NOCTTY)open(path, O_WRONLY | O_NOCTTY) Closing any file descriptor to the same file will release the lock. 任何文件描述符关闭到同一文件将释放锁定。

Some may say that re-setting the lock memebers before the second fcntl() call is unnecessary, but I'd rather err on the side of caution here. 有人可能说没有必要在第二次fcntl()调用之前重新设置lock ,但是我宁愿在此谨慎一点。

As to how to report it, I would simply use 至于如何举报,我会简单地使用

int    fd;
pid_t  p;

fd = open(path, O_RDWR | O_NOCTTY);
if (fd == -1) {
    fprintf(stderr, "%s: Cannot open file: %s.\n",
                    path, strerror(errno));
    exit(EXIT_FAILURE);
}

p = lock_exclusively(fd);
if (p < 0) {
    fprintf(stderr, "%s: Cannot lock file: %s.\n",
                    path, strerror(errno));
    exit(EXIT_FAILURE);
} else
if (p > 0) {
    fprintf(stderr, "%s: File is already locked by process %ld.\n",
                    path, (long)p);
    exit(EXIT_FAILURE);
}

/* fd is now open and exclusive-locked. */

The user can always run eg ps -o cmd= -p PID to see what command that is (or you can try reading /proc/PID/cmdline in Linux). 用户可以始终运行例如ps -o cmd= -p PID来查看是什么命令(或者您可以尝试在Linux中读取/proc/PID/cmdline )。

From the example code: 从示例代码中:

printf ("locking\n");
/* Initialize the flock structure. */
memset (&lock, 0, sizeof(lock));
lock.l_type = F_WRLCK;
/* Place a write lock on the file. */
fcntl (fd, F_SETLKW, &lock);

printf ("locked; hit Enter to unlock... ");

You need to change the fcntl (fd, F_SETLKW, &lock); 您需要更改fcntl (fd, F_SETLKW, &lock); to: 至:

if (fcntl (fd, F_SETLK, &lock) == -1) {
  printf ("File is locked by pid %i\n", lock.l_pid);
  return 0;
}

The F_SETLKW command blocks if it cannot get the lock. 如果无法获得锁定,则F_SETLKW命令将阻塞。 F_SETLK will return if it cannot get the lock. 如果无法获得锁,则F_SETLK将返回。 Really the code should also check errno == EACCESS or errno == EAGAIN after getting the -1 return value. 确实,代码在获得-1返回值之后还应该检查errno == EACCESSerrno == EAGAIN

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM