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

为何fork()中使用flock()会通过不同文件描述符重复锁定同一文件?

问题分析与解决

你的代码出现这种现象,核心原因是进程调度的时序问题,加上锁的持有时间太短:

  1. 当fork()后,父进程和子进程的执行顺序由操作系统调度器决定。如果父进程先完成整个流程:打开文件→加排他锁→打印→关闭文件(关闭文件会自动释放该进程持有的文件锁),此时子进程才开始执行,文件锁已经被释放,子进程自然能成功获取锁并打印。

  2. 另外你的open调用存在参数错误:open的第二个参数是打开标志(如O_WRONLY、O_CREAT),第三个参数才是文件权限(0600)。你把权限值放到了标志位参数里,属于未定义行为,正确写法:

    • 文件已存在时:int id = open("shared.txt", O_WRONLY);
    • 需要创建文件时:int id = open("shared.txt", O_WRONLY | O_CREAT, 0600);

验证互斥效果的修改方案

要看到预期的“一个进程锁定,另一个阻塞”效果,需要让持有锁的进程保持锁一段时间,比如在printf后添加sleep,避免锁被立即释放:

#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <fcntl.h>

int main() {
    int i = fork();

    if (!i){
        int id = open("shared.txt", O_WRONLY);
        if(flock(id, LOCK_EX) == 0) {
            printf("child\n");
            sleep(5); // 持有锁5秒
        }
        close(id);
    }
    else {
        int id = open("shared.txt", O_WRONLY);
        if(flock(id, LOCK_EX) == 0) {
            printf("parent\n");
            sleep(5); // 持有锁5秒
        }
        close(id);
        wait(NULL);
    }

    return 0;
}

修改后,无论哪个进程先获取锁,都会持有锁5秒,另一个进程的flock会被阻塞,直到锁被释放,你会看到一个进程先打印,5秒后另一个进程才输出内容。

补充:flock核心特性

  • flock的锁默认是建议性锁,只有所有访问文件的进程都遵守锁协议时,互斥才会生效;
  • 锁与进程+文件inode绑定:同一个进程对同一个inode的多个文件描述符,锁是共享的;不同进程对同一个inode的文件描述符,排他锁互斥;
  • 进程关闭任意一个指向该inode的文件描述符,或进程退出时,对应inode的flock锁会自动释放。

内容的提问来源于stack exchange,提问作者Єгорій

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:10:25