You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

改进lockdemo.c文件锁代码:如何阻止文件被追加写入?

How to Prevent Appending to a Locked File with fcntl

Problem Description

I found a file locking code snippet (lockdemo.c) online that runs correctly, but it doesn't meet my needs: when the file is locked, I can still append data to lockdemo.c. How can I prevent this behavior?

Here's the original code:

/* ** lockdemo.c -- shows off your system's file locking. Rated R. */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
    /* l_type l_whence l_start l_len l_pid */
    struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, 0 };
    int fd;

    fl.l_pid = getpid();

    if (argc > 1)
        fl.l_type = F_RDLCK;

    if ((fd = open("lockdemo.c", O_RDWR)) == -1) {
        perror("open");
        exit(1);
    }

    printf("Press <RETURN> to try to get lock: ");
    getchar();

    printf("Trying to get lock...");
    if (fcntl(fd, F_SETLKW, &fl) == -1) {
        perror("fcntl");
        exit(1);
    }

    printf("got lock\n");
    printf("Press <RETURN> to release lock: ");
    getchar();

    fl.l_type = F_UNLCK;  /* set to unlock same region */
    if (fcntl(fd, F_SETLK, &fl) == -1) {
        perror("fcntl");
        exit(1);
    }

    printf("Unlocked.\n");
    close(fd);
}

Why the Original Code Doesn't Block Appends

The fcntl locks you're using are advisory locks—this is the default behavior on Unix-like systems. Advisory locks don't enforce access to the file; they only work if every process that accesses the file voluntarily checks the lock status before performing operations. If a process skips checking the lock and writes directly, the kernel won't stop it.

Your original code locks the entire file (setting l_len = 0 means "lock from l_start to the end of the file, including any future extensions"), but this only blocks other processes that also attempt to acquire a conflicting lock.

Solutions to Block Unlocked Appends

The most reliable and portable approach is to ensure every process that writes to lockdemo.c first checks for and acquires the appropriate lock before writing.

Here's an example of an append program that follows this rule—if lockdemo holds the lock, this program will wait until the lock is released before writing:

// safe_append.c -- appends to lockdemo.c only when no lock is held
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd;
    struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};

    // Open the file for appending
    if ((fd = open("lockdemo.c", O_WRONLY | O_APPEND)) == -1) {
        perror("open failed");
        exit(EXIT_FAILURE);
    }

    // Wait to acquire an exclusive write lock
    printf("Waiting for lock to append...\n");
    if (fcntl(fd, F_SETLKW, &fl) == -1) {
        perror("failed to acquire lock");
        close(fd);
        exit(EXIT_FAILURE);
    }

    // Now safely append data
    const char* data = "This is a safe append.\n";
    if (write(fd, data, sizeof(data)-1) == -1) {
        perror("write failed");
    }

    // Release the lock
    fl.l_type = F_UNLCK;
    if (fcntl(fd, F_SETLK, &fl) == -1) {
        perror("failed to release lock");
    }

    close(fd);
    printf("Append successful.\n");
    return EXIT_SUCCESS;
}

2. Use Mandatory Locking (Alternative, Less Portable)

If you need to block processes that don't check locks voluntarily, you can enable mandatory locking, which forces the kernel to enforce lock rules. However, this has limitations:

  • Not all file systems support mandatory locking (e.g., ext4 does, but some network file systems don't).
  • It requires specific file system mount options and file permissions.

To set up mandatory locking:

  1. Remount the file system with the mand option (replace /path/to/your/fs with your actual mount point):
    sudo mount -o remount,mand /path/to/your/fs
    
  2. Set the setgid bit on lockdemo.c and remove the group execute permission (this tells the kernel to enforce locks on the file):
    chmod g+s,g-x lockdemo.c
    

Once enabled, any process that tries to write to lockdemo.c while it's locked will be blocked by the kernel, even if it doesn't check the lock.

Final Notes

Advisory locking is almost always the better choice—it's more portable, has fewer performance overheads, and avoids edge cases that come with mandatory locking. Only use mandatory locking if you have no control over the other processes writing to the file.

内容的提问来源于stack exchange,提问作者stack12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 15:34:07