代码之家  ›  专栏  ›  技术社区  ›  RLe

fcntl如何知道哪个进程保存锁文件?

  •  0
  • RLe  · 技术社区  · 6 年前

    我是fcntl锁的新手,下面这个例子使用C代码在Linux中创建一个示例锁: http://www.informit.com/articles/article.aspx?p=23618&seqNum=4

    我想知道我们怎样才能打印出哪个进程保存锁文件,哪个进程正在等待锁。我考虑使用L&PID来确定持有锁的进程ID,但我不确定正确的方法。 打印哪个进程持有锁的最佳方法是什么?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Nominal Animal    6 年前

    作为 man 2 fcntl 页面描述,您可以使用 F_GETLK 获取具有冲突锁的进程ID(如果冲突锁是进程关联锁)。例如,

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

    请注意 fd 必须开放阅读和写作。我建议使用 open(path, O_RDWR | O_NOCTTY) open(path, O_WRONLY | O_NOCTTY) . 关闭 任何 同一文件的文件描述符将释放锁。

    有人可能会说,重新设置 lock 在第二个之前 fcntl() 打电话是不必要的,但我宁愿在这里犯错。

    至于如何报告,我只需使用

    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. */
    

    用户始终可以运行,例如 ps -o cmd= -p PID 查看这是什么命令(或者您可以尝试阅读 /proc/PID/cmdline 在Linux中)。

        2
  •  0
  •   Tom D    6 年前

    从示例代码中:

    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... ");
    

    你需要改变 fcntl (fd, F_SETLKW, &lock); 到:

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

    如果无法获取锁,f_setlkw命令将阻止。如果不能获得锁,f_setlk将返回。真的,代码也应该检查 errno == EACCESS errno == EAGAIN 获取-1返回值后。