C语言建议性文件锁程序无法锁定文件,请求故障排查
你的建议性文件锁失效的原因与修复方案
嘿,我帮你梳理了代码里的几个关键错误,正是这些问题导致锁机制完全不起作用:
1. 最致命的错误:混淆文件描述符和文件流指针
你把fopen()返回的FILE*(文件流指针)直接赋值给了int fd(文件描述符),但fcntl()系统调用只认整数类型的文件描述符!这就好比你拿一把汽车钥匙去开房门——完全不匹配,锁操作自然直接失效。
另外,open()的第二个参数是宏常量(比如O_WRONLY、O_RDWR),不是字符串"w"!你用字符串会被编译器转成乱码整数,导致open调用直接失败,后续逻辑全走偏了。
2. 锁的类型和逻辑完全混乱
- 你要阻止其他进程编辑文件,应该用
F_WRLCK(排他写锁),但你设置的是F_RDLCK(共享读锁)——读锁本来就允许多个进程同时读,根本拦不住编辑。 - 你的
Lock()函数刚把锁加上,立刻又解锁了,锁的生命周期连一瞬间都不到,其他进程根本没机会察觉到锁的存在。
3. 文件操作的资源管理一团糟
你反复打开、关闭文件,还多次给同一个fd变量乱赋值,导致文件描述符要么泄漏,要么指向错误的资源。比如readfile()函数里,你明明传了fPtr参数,结果却用全局变量fd来读,这完全是驴唇不对马嘴。
4. 还有几个细节小错误
main()函数的标准返回类型是int,不是void,虽然编译器可能放过,但这是C语言的基本规范。Add()函数里的fgets会读取之前scanf留下的换行符,导致你输入的内容直接为空,这个体验也很差。
修复后的完整代码
我把这些问题都修好了,你可以直接参考:
#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]; // 全局文件描述符,保持文件打开以持有锁 int fd = -1; struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0}; void clrscr(); void Operations(); void Add(); void readfile(int fd); int LockFile(); void UnlockFile(); int main() { do { clrscr(); // 以读写+创建的方式打开文件,获取文件描述符 fd = open("demo.txt", O_RDWR | O_CREAT, 0666); if (fd == -1) { perror("Failed to open file"); sleep(2); continue; } // 先检查文件是否被其他进程锁定 fl.l_type = F_WRLCK; if (fcntl(fd, F_GETLK, &fl) == -1) { perror("Failed to check lock status"); } else if (fl.l_type != F_UNLCK) { printf("File is locked by process %d - only read access allowed\n", fl.l_pid); readfile(fd); close(fd); fd = -1; sleep(3); continue; } else { printf("File is available, locking for editing...\n"); if (LockFile() == 0) { printf("Lock acquired successfully!\n"); readfile(fd); } } printf("\n\t\t***** SIMPLE TEXT EDITOR WITH ADVISORY LOCKING *****\n"); Operations(); // 操作完成后解锁并关闭文件 if (fd != -1) { UnlockFile(); close(fd); fd = -1; } } while(1); return 0; } // 获取排他写锁 int LockFile() { if (fd == -1) return -1; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; // 0表示锁定整个文件 fl.l_pid = getpid(); if (fcntl(fd, F_SETLK, &fl) == -1) { perror("Failed to set exclusive lock"); return -1; } return 0; } // 释放锁 void UnlockFile() { if (fd == -1) return; fl.l_type = F_UNLCK; if (fcntl(fd, F_SETLK, &fl) == -1) { perror("Failed to unlock file"); } else { printf("File unlocked successfully\n"); } } void clrscr() { system("@cls||clear"); } void Operations() { printf("\n\n\tAvailable Operations:\n"); printf("\t1. Append to File\n\t2. Delete File\n\t3. Exit\n"); printf("\n\tEnter your choice: "); // 清除scanf遗留的换行符,避免影响后续fgets while(getchar() != '\n'); scanf("%d", &controller); switch(controller) { case 1: Add(); break; case 2: if (fd != -1) { close(fd); fd = -1; } if (remove("demo.txt") == 0) { printf("File deleted!\n"); } else { perror("Failed to delete file"); } sleep(2); break; case 3: if (fd != -1) { UnlockFile(); close(fd); } exit(EXIT_SUCCESS); default: printf("Invalid choice, try again\n"); sleep(2); } } void Add() { if (fd == -1) { printf("Can't edit - file is not locked or available\n"); sleep(2); return; } printf("Enter content to append: \n"); while(getchar() != '\n'); // 清除换行符 fgets(data, sizeof(data), stdin); // 移动到文件末尾写入 lseek(fd, 0, SEEK_END); write(fd, data, strlen(data)); printf("Content added successfully!\nUpdated file content:\n\t"); lseek(fd, 0, SEEK_SET); readfile(fd); sleep(3); } void readfile(int file_fd) { char c; // 逐个字符读取文件内容 while (read(file_fd, &c, 1) > 0) { printf("%c", c); } printf("\n"); // 重置文件指针到开头 lseek(file_fd, 0, SEEK_SET); }
修复要点说明
- 统一使用文件描述符:全程用
open()/close()/fcntl(),彻底抛弃fopen()的混用问题,确保锁操作有效。 - 正确的锁类型:用
F_WRLCK排他锁,真正阻止其他进程的写操作。 - 合理的锁生命周期:在文件打开期间持有锁,操作完成后才解锁,让其他进程有机会检测到锁的存在。
- 锁检查逻辑:打开文件后先调用
F_GETLK检查是否有其他进程持锁,符合建议性锁的使用规范。 - 修复输入问题:解决了
scanf和fgets的换行冲突,避免输入为空的问题。
最后要提醒你:建议性锁的前提是所有访问文件的进程都主动检查锁,如果有进程直接打开文件而不调用fcntl检查锁,它依然能编辑文件——这是Unix/Linux建议性锁的设计特性,不是代码bug哦。
内容的提问来源于stack exchange,提问作者xxxxxxxxxxxxxx
相关产品推荐
相关产品推荐

