Bob Cheng
System Programming

File Record Lock

Why Lock?

問題: 多個 process 可能在同一時間存取同個檔案 以下圖為例,A 在 read() 時,B 正在 write(),導致資料衝突

解決辦法:

  • File Locking: 確保對整個檔案進行唯一存取的機制
  • Record (or bytes range) Locking: 確保對特定資料區塊進行唯一存取的機制

How

  • Unix System allows a process to exclusively lock a file to prevent other processes from reading or writing the same file
  • When a lock is granted to a process, the process has the right to read/write the file
  • When a lock is denied, the process cannot get the lock until the lock is released by the lock holder

使用以下函數來實現 lock :

lock entire file : flock()

// returns: 0 on success, −1 on error
int flock(int fd, int operation);

flock() apply or remove lock on an open file

operation :

  • LOCK_SH : 設定 shared lock — 指定時間內可以有多個 process 獲取該 lock
  • LOCK_EX : 設定 exclusive lock — 指定時間內只能有一個 process 獲取該 lock
  • LOCK_UN : 解除 lock

lock regions of file : fcntl()

// The value returned on a success call depends on cmd; -1 is returned on error
int fcntl(int fd, int cmd, ... /* struct flock *flockptr */);
  • cmd :

    • F_GETLK : 確認目前的 flock 是否可被設置在 fd 上 如果可以上鎖,不會執行上鎖,而是將原本 flockl_type 覆蓋成 F_UNLCK 如果不行上鎖,將 flock 的參數覆蓋成所有造成阻擋的 locks 之一
    • F_SETLK : 根據 flock 來對指定的區塊設定或解除 lock (non-blocking)
    • F_SETLKW : 與 F_SETLK 相同,但如果碰上 lock 被占用,會等到 lock 被釋放 (blocking)
  • flockptr : 指向 struct flock 的 pointer

    struct flock {
    	short l_type;   /* F_RDLCK, F_WRLCK, F_UNLCK */
    	short l_whence; /* SEEK_SET, SEEK_CUR, or SEEK_END, same as the whence in lseek*/
    	off_t l_start;  /* offset in bytes relative to whence */
    	off_t l_len;    /* length, in bytes, 0 means lock to EOF*/
    	pid_t l_pid;    /* filled in by F_GETLK, ignore otherwise */
    }

    l_type 的三種設定值:

    • F_RDLCK : shared read lock — multiple readers but no writers
    • F_WRLCK : exclusive write lock — single writer and no reader
    • F_UNLCK : unlocking a region
  • To obtain a read lock, the fd must be open for reading (similarly for write)
  • fcntl() 不是 atomic operation — 先用 F_GETLK 來確認可否上鎖,再用 F_SETLK 上鎖,兩個操作可能會有其他 process 介入

Advisory v.s. Mandatory

  • Advisory locking 建議鎖
    • lock functions : flock(), fcntl(), lockf()
    • 「防君子不防小人」 — 每個 process 在存取共享檔案時會呼叫 lock functions 來確認鎖的狀態,再決定是否存取。但此規則並非強制,如果有 process 打從一開始便沒有使用 lock functions,便無法防止其存取共享檔案。
  • Mandatory locking 強制鎖 OS kernel 會檢查每一個對於檔案的操作,來確認有沒有 process 違反規則

鎖的繼承

  • 當一個 process 結束,它所設定的所有 lock 都會被釋放
  • 當一個 fd 被關閉,它上面的所有鎖都會被釋放
  • 當一個 process A 產生了 process B,A 具有的 locks 不會被 B 繼承 (見 /notes/school/sp/process-control)