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

C语言建议性文件锁程序无法锁文件,请求排查代码错误

Let's walk through all the bugs in your code that are breaking the advisory file locking, plus other critical issues that are messing up basic functionality:


Key Issues Causing Lock Failure & Functionality Errors

1. Incorrect Mix of System Calls and Standard I/O Functions

You're using low-level system calls (open, fcntl) and standard C I/O functions (fopen, fdopen) incorrectly, leading to invalid file handles and undefined behavior:

  • open() requires integer flags (like O_WRONLY, O_CREAT) as its second argument, not a string like "w". Your call open("demo.txt", "w") is invalid and will always return -1 (error).
  • fdopen() takes a file descriptor (integer) as its first argument, not a filename. Using fdopen("demo.txt", "w") is a type mismatch that corrupts your file handle.
  • You're assigning FILE* pointers to int variables (e.g., fd = fopen("demo.txt", "r")), which completely breaks the value of fd and makes all subsequent operations on it invalid.

2. Broken Locking Logic

Your locking implementation is fundamentally flawed:

  • fcntl() requires a file descriptor, not a FILE* pointer. In Lock(), you pass a FILE* directly to fcntl()—you need to use fileno(fd) to get the descriptor from a FILE*, or use open() instead of fopen() for locking operations.
  • You're using a read lock (F_RDLCK) when you need an exclusive write lock (F_WRLCK) for editing. Read locks are shared, so multiple processes can hold them at the same time, which defeats your goal of preventing concurrent edits.
  • The Lock() function immediately unlocks the file right after setting the lock. The logic checks fl.l_type != F_UNLCK (which is always true after setting F_RDLCK) and then sets fl.l_type = F_UNLCK, so you never actually keep the lock held for edits.
  • Advisory locks only work if all processes accessing the file check the lock before modifying it. Your Add() function opens the file and writes to it without any lock checks, so it completely bypasses the locking mechanism.

3. Invalid File Reading

The readfile() function has a critical type mismatch:

  • It accepts a FILE* fPtr as an argument but uses the global int fd (a file descriptor, not a FILE*) with getc(). getc() expects a FILE*, so this will cause crashes or garbage output.

4. Other Minor Bugs

  • void main() is not a standard C signature—use int main(void) instead.
  • Edit() and Delete() are declared but never implemented or called.
  • After scanf() in Operations(), a leftover newline remains in the input buffer, causing fgets() in Add() to read an empty line immediately.

Fixed Code Example

Here's a corrected version of your program that implements proper advisory locking:

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int controller;
char data[1000];

// Lock structure (initialized for unlocked state)
struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};

void clrscr();
void Operations();
void Add();
void readfile(FILE *fPtr);
int acquire_exclusive_lock(int fd);
void release_lock(int fd);

int main(void) {
    do {
        clrscr();
        // Open file for reading (create if it doesn't exist)
        int fd = open("demo.txt", O_RDONLY | O_CREAT, 0644);
        if (fd == -1) {
            perror("Failed to open file");
            continue;
        }

        FILE *fp = fdopen(fd, "r");
        if (!fp) {
            perror("Failed to convert file descriptor to FILE*");
            close(fd);
            continue;
        }

        printf("Contents of the file are:\n\t");
        readfile(fp);
        fclose(fp); // Closes both the FILE* and underlying descriptor

        printf("\n\n***** WELCOME USER! THIS IS A SIMPLE TEXT EDITOR *****\n");
        Operations();
    } while(1);

    return 0;
}

// Acquire exclusive write lock for editing
int acquire_exclusive_lock(int fd) {
    fl.l_type = F_WRLCK;
    fl.l_pid = getpid();

    if (fcntl(fd, F_SETLK, &fl) == -1) {
        if (errno == EACCES || errno == EAGAIN) {
            printf("File is locked by another process - cannot edit.\n");
            return 0;
        } else {
            perror("Failed to acquire lock");
            return 0;
        }
    }
    printf("Exclusive lock acquired (PID: %d)\n", getpid());
    return 1;
}

// Release the file lock
void release_lock(int fd) {
    fl.l_type = F_UNLCK;
    if (fcntl(fd, F_SETLK, &fl) == -1) {
        perror("Failed to release lock");
    } else {
        printf("Lock released.\n");
    }
}

void clrscr() {
    system("clear || cls");
}

void Operations() {
    printf("\nOperations you can perform here:\n");
    printf("1. ADD TO FILE\n");
    printf("2. DELETE THE FILE\n");
    printf("3. EXIT\n");
    printf("\nEnter your choice: ");
    
    // Clear leftover newline from input buffer
    while ((getchar()) != '\n');
    scanf("%d", &controller);

    switch(controller) {
        case 1: Add(); break;
        case 2: 
            if (remove("demo.txt") == 0) {
                printf("File deleted successfully.\n");
            } else {
                perror("Failed to delete file");
            }
            break;
        case 3: 
            printf("Exiting...\n");
            exit(EXIT_SUCCESS);
        default:
            printf("Invalid choice!\n");
    }

    printf("\nPress Enter to continue...");
    while ((getchar()) != '\n');
    getchar();
}

void Add() {
    // Open file for appending (create if needed)
    int fd = open("demo.txt", O_WRONLY | O_APPEND | O_CREAT, 0644);
    if (fd == -1) {
        perror("Failed to open file for writing");
        return;
    }

    // Acquire lock before writing
    if (!acquire_exclusive_lock(fd)) {
        close(fd);
        return;
    }

    printf("Enter contents to store in file:\n");
    // Clear input buffer first
    while ((getchar()) != '\n');
    fgets(data, sizeof(data), stdin);

    // Clean up newline from fgets and add proper line break
    data[strcspn(data, "\n")] = '\0';
    strcat(data, "\n");

    if (write(fd, data, strlen(data)) == -1) {
        perror("Failed to write to file");
    } else {
        printf("Data added to the file successfully!\n");
    }

    // Release lock and close file
    release_lock(fd);
    close(fd);

    // Show updated file contents
    printf("\nUpdated file contents:\n\t");
    int read_fd = open("demo.txt", O_RDONLY);
    if (read_fd != -1) {
        FILE *fp = fdopen(read_fd, "r");
        if (fp) {
            readfile(fp);
            fclose(fp);
        } else {
            close(read_fd);
        }
    }
}

void readfile(FILE *fPtr) {
    char c = getc(fPtr);
    while (c != EOF) {
        printf("%c", c);
        c = getc(fPtr);
    }
}

Key Fixes Explained:

  • Separated file descriptor and FILE* usage correctly, using open() for system-level operations (locking, writing) and fdopen() only when needed for standard I/O.
  • Implemented proper exclusive lock acquisition (F_WRLCK) with error handling for locked files.
  • Ensured all write operations first check and acquire the lock before modifying the file.
  • Fixed input buffer issues to avoid empty fgets() calls.
  • Added proper error reporting with perror() to diagnose issues quickly.

Remember: For advisory locking to work fully, any other process that accesses demo.txt must also implement the same lock-checking logic.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:07:14