[英]fcntl how to know which process hold lock file?
我是fcntl鎖定的新手,並按照以下示例使用c代碼在linux中創建了示例鎖定: http : //www.informit.com/articles/article.aspx? p=23618&seqNum =4
我想知道我們如何才能打印出哪個進程持有鎖定文件以及哪個進程正在等待鎖定。 我考慮使用l_pid來找出持有鎖的進程ID,但是我不確定這樣做的正確方法。 打印出哪個進程持有鎖的最佳方法是什么?
如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)
。 將任何文件描述符關閉到同一文件將釋放鎖定。
有人可能說沒有必要在第二次fcntl()
調用之前重新設置lock
,但是我寧願在此謹慎一點。
至於如何舉報,我會簡單地使用
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
來查看是什么命令(或者您可以嘗試在Linux中讀取/proc/PID/cmdline
)。
從示例代碼中:
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將返回。 確實,代碼在獲得-1返回值之后還應該檢查errno == EACCESS
或errno == EAGAIN
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.