โมดูล fcntl เป็น Interface ไปยัง fcntl() และ ioctl() System Calls ของ UNIX สำหรับควบคุม File Descriptor และ I/O
import fcntl
เมธอดหลัก
fcntl.fcntl(fd, op[, arg])
ทำ Operation บน File Descriptor
fd: File Descriptor (int หรือ io.IOBase)op: Operation Code (F_GETFL, F_SETFL, F_GETFD, F_SETFD, F_GETLK, F_SETLK, F_SETLKW)arg: Optional Argument (int หรือ bytes)
fcntl.ioctl(fd, op[, arg[, mutate_flag]])
เหมือน fcntl แต่ Argument Handling ซับซ้อนกว่า รองรับ Mutable Buffer
fcntl.flock(fd, op)
File Locking แบบง่าย (BSD Style)
LOCK_SH- Shared Lock (อ่านพร้อมกันได้)LOCK_EX- Exclusive Lock (เขียน/อ่าน独占)LOCK_UN- UnlockLOCK_NB- Non-blocking (รวมกับ Flag อื่น)
fcntl.lockf(fd, operation[, length[, start[, whence]]])
Wrapper สำหรับ Locking (POSIX Style) รองรับ Lock บางส่วนของไฟล์
ตัวอย่าง: File Locking เพื่อ Counter แบบ Thread-Safe
import fcntl, os, time
counter_file = 'my_counter.txt'
# สร้างไฟล์เริ่มต้น
if not os.path.exists(counter_file):
with open(counter_file, 'w') as f:
f.write('0')
for i in range(15):
with open(counter_file, 'r+') as f:
fcntl.flock(f.fileno(), fcntl.LOCK_EX) # Exclusive Lock
count = int(f.readline()) + 1
f.seek(0)
f.write(str(count))
f.truncate()
fcntl.flock(f.fileno(), fcntl.LOCK_UN) # Unlock
print(f'PID: {os.getpid()}, Count: {count}')
time.sleep(0.2)
ผลลัพธ์
PID: 12698, Count: 1 PID: 12698, Count: 2 ... PID: 12698, Count: 15 $ cat my_counter.txt 15
กรณีใช้งานจริง
- PID File Locking (ป้องกันรันซ้ำ)
- Config File Atomic Update
- Log Rotation Coordination
- Inter-process Synchronization
ข้อควรระวัง
- Lock เป็น Advisory (Process ต้องร่วมมือกัน Lock/Unlock)
- Network File Systems (NFS) อาจไม่รองรับ Locking ได้เต็มที่
- ใช้
withStatement เพื่อให้ Unlock อัตโนมัติ