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 獲取該 lockLOCK_EX
: 設定 exclusive lock — 指定時間內只能有一個 process 獲取該 lockLOCK_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 上 如果可以上鎖,不會執行上鎖,而是將原本 flock 的 l_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 writersF_WRLCK
: exclusive write lock — single writer and no readerF_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)