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 (likeO_WRONLY,O_CREAT) as its second argument, not a string like"w". Your callopen("demo.txt", "w")is invalid and will always return-1(error).fdopen()takes a file descriptor (integer) as its first argument, not a filename. Usingfdopen("demo.txt", "w")is a type mismatch that corrupts your file handle.- You're assigning
FILE*pointers tointvariables (e.g.,fd = fopen("demo.txt", "r")), which completely breaks the value offdand makes all subsequent operations on it invalid.
2. Broken Locking Logic
Your locking implementation is fundamentally flawed:
fcntl()requires a file descriptor, not aFILE*pointer. InLock(), you pass aFILE*directly tofcntl()—you need to usefileno(fd)to get the descriptor from aFILE*, or useopen()instead offopen()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 checksfl.l_type != F_UNLCK(which is always true after settingF_RDLCK) and then setsfl.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* fPtras an argument but uses the globalint fd(a file descriptor, not aFILE*) withgetc().getc()expects aFILE*, so this will cause crashes or garbage output.
4. Other Minor Bugs
void main()is not a standard C signature—useint main(void)instead.Edit()andDelete()are declared but never implemented or called.- After
scanf()inOperations(), a leftover newline remains in the input buffer, causingfgets()inAdd()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, usingopen()for system-level operations (locking, writing) andfdopen()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
相关产品推荐
相关产品推荐

