Fundamentals 14 min read

Understanding the Differences Between flock, lockf, and fcntl for Linux File Locking

This article explains how the Linux file‑locking interfaces flock, lockf, and fcntl differ in scope, behavior, and interaction, providing detailed function prototypes, option tables, and multiple C code examples that illustrate locking across duplicated descriptors, forked processes, and exec calls.

ITPUB
ITPUB
ITPUB
Understanding the Differences Between flock, lockf, and fcntl for Linux File Locking

1. flock

The flock(int fd, int operation) system call applies or removes an advisory lock on the entire file referenced by fd. The operation argument can be one of:

LOCK_SH – shared lock

LOCK_EX – exclusive lock

LOCK_UN – unlock

LOCK_NB – non‑blocking (used with the above)

Key characteristics:

Locks the whole file; it cannot lock a specific region.

Creates only advisory locks.

The lock is associated with the file’s struct file entry, not the file descriptor, so duplicated descriptors (via dup or after fork) share the same lock.

Closing one duplicated descriptor does not release the lock; the lock is released only when all descriptors referencing the same struct file are closed.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/file.h>
int main(int argc, char **argv) {
    int fd1 = open("./tmp.txt", O_RDWR);
    int fd2 = dup(fd1);
    printf("fd1: %d, fd2: %d
", fd1, fd2);
    int ret = flock(fd1, LOCK_EX);
    printf("get lock1, ret: %d
", ret);
    ret = flock(fd2, LOCK_EX);
    printf("get lock2, ret: %d
", ret);
    return 0;
}

Running this program shows that locking via fd1 does not prevent fd2 (a duplicate) from acquiring the same lock, because they refer to the same underlying file object.

A second example demonstrates that a child process created with fork can acquire an exclusive lock on the same file descriptor without being blocked by the parent’s lock, confirming that flock locks are not inherited across fork.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/file.h>
int main(int argc, char **argv) {
    int fd = open("./tmp.txt", O_RDWR);
    pid_t pid = fork();
    if (pid == 0) { // child
        int ret = flock(fd, LOCK_EX);
        printf("child get lock, fd: %d, ret: %d
", fd, ret);
        sleep(10);
        exit(0);
    }
    int ret = flock(fd, LOCK_EX);
    printf("parent get lock, fd: %d, ret: %d
", fd, ret);
    return 0;
}

Additional observations about flock:

Opening the same file twice (two separate open calls) yields independent file structures; a lock on one descriptor does not affect the other.

Locks are released automatically on exec unless the descriptor has the close‑on‑exec flag. flock does not work on NFS; use fcntl instead.

The lock is recursive: a process can lock the same file multiple times via duplicated descriptors without deadlock.

2. lockf and fcntl

The library function int lockf(int fd, int cmd, off_t len) is a thin wrapper around fcntl. Its cmd values are:

F_LOCK – block until an exclusive lock is obtained.

F_TLOCK – non‑blocking exclusive lock; returns error if unavailable.

F_ULOCK – unlock.

F_TEST – test lock status (0 if unlocked, -1 if locked). len specifies the length of the region to lock starting from the current file offset; lockf only supports exclusive locks.

The more general fcntl interface uses struct flock:

struct flock {
    short   l_type;   /* F_RDLCK, F_WRLCK, F_UNLCK */
    short   l_whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
    off_t   l_start;  /* start offset */
    off_t   l_len;    /* length */
    pid_t   l_pid;    /* PID of locking process (F_GETLK) */
};

Relevant fcntl commands:

F_SETLK – attempt to set a lock (shared or exclusive) without blocking.

F_SETLKW – same as F_SETLK but blocks until the lock can be acquired.

F_GETLK – query lock information; fills the supplied struct flock with details of any conflicting lock.

Key differences and capabilities: fcntl can lock whole files or specific byte ranges, and supports both shared and exclusive locks.

Locks set with fcntl are released when the associated file descriptor is closed, unlike flock where closing one duplicated descriptor does not release the lock.

Locks are not inherited across fork (different from flock).

After an exec, locks are retained unless the descriptor has the close‑on‑exec flag.

Mandatory locking can be enabled by setting the set‑gid bit on the file and clearing the group‑execute bit, and mounting the filesystem with the appropriate option.

3. Interaction Between flock and lockf/fcntl

Locks created by flock and those created by lockf / fcntl are independent; one does not affect the other. The following test program demonstrates this:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
int main(int argc, char **argv) {
    int fd = open("./tmp.txt", O_RDWR);
    int ret = flock(fd, LOCK_EX);
    printf("flock return ret : %d
", ret);
    ret = lockf(fd, F_LOCK, 0);
    printf("lockf return ret: %d
", ret);
    sleep(100);
    return 0;
}

Running it yields:

flock return ret : 0
lockf return ret: 0

Both calls succeed, confirming that the two locking mechanisms operate on separate lock namespaces. The /proc/locks file can be inspected to see both a POSIX (fcntl/lockf) lock and an FLOCK lock for the same process.

Key takeaways: flock locks whole files and are advisory; they are associated with the file object, not the descriptor. lockf / fcntl can lock byte ranges, support shared locks, and are tied to the descriptor.

Both mechanisms can coexist without interfering, but using both on the same file can lead to confusing lock states, so it is advisable to choose one API consistently.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

file lockingflockfcntllockf
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.