我们在 Linux 环境中用 C 编程时,如果对文件读写,Linux 会自动给文件加锁嘛?以及怎么加文件锁?

news2024/9/20 22:27:20

task1: 验证Linux不会自动给文件加锁

先说结论,结论是不会

我写了一个这样的程序

#include <stdio.h>
#include <unistd.h>

int main() {
    const char* pathname = "your_file_pathname.txt";
    FILE* file = NULL;
    int count = 100;

    if(access(pathname, F_OK) == 0) {
        file = fopen(pathname, "r+"); 
        printf("open in r+ mode\n");
    }
    else {
        file = fopen(pathname, "w+"); 
        printf("open in w+ mode\n");
    }

    if (file == NULL) {
        printf("无法打开文件\n");
        return 1;
    }

    fseek(file, 0, SEEK_END); // 将文件指针移动到文件末尾
    long file_size = ftell(file); // 获取文件大小

    if (file_size == 0) {
        fprintf(file, "0\n"); // 文件为空,写入0
        fflush(file); // 刷新文件缓冲区,确保写入文件
    }
    

    fseek(file, 0, SEEK_SET); // 将文件指针移动到文件开头
    int num;
    fscanf(file, "%d", &num); // 读取文件中的整数
    printf("num = %d\n", num);
    sleep(2);

    while(count--) {
        num++; // 将整数加1
        fseek(file, 0, SEEK_SET); // 将文件指针移动到文件开头
        fprintf(file, "%d\n", num); // 将更新后的整数写回文件
        fflush(file); // 刷新文件缓冲区,确保写入文件
        fseek(file, 0, SEEK_SET); // 将文件指针移动到文件开头
        fscanf(file, "%d", &num); // 读取文件中的整数
        printf("num = %d\n", num);
        sleep(2);
    }

    fclose(file); // 关闭文件

    return 0;
}

上面这个程序会读取文件中的数字,然后给数字+1,再写回文件

这个程序里没有给文件加锁,我同时运行了 8 个这样的程序,最后的 result file 里的数字是 127,而非 800,说明 Linux 本身并不会给文件加锁

task2: 如何手动给文件加锁?

首先根据 ChatGPT,我们可以获得如下代码(经过部分注释和修改,可以根据注释理解源码):

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd;

    // 打开文件
    fd = open("file.txt", O_WRONLY);
    if (fd == -1) {
        perror("open");
        exit(1);
    }

    // 设置文件锁
    // 我们定义了一个struct flock结构体来描述文件锁的属性,包括锁的类型、起始位置和长度。
    struct flock lock;
    lock.l_type = F_WRLCK;   // 写锁
    // short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
    // __off_t l_start;	/* Offset where the lock begins.  */
    // l_whence 和 l_start 是共同指定锁的起始位置的
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    // __off_t l_len;	/* Size of the locked area; zero means until EOF.  */
    lock.l_len = 0;          // 锁定整个文件

    // 接下来,我们使用fcntl函数来获取文件锁,使用F_SETLKW标志表示在获取锁时阻塞进程,直到锁可用。
    // #  define F_SETLKW	7	/* Set record locking info (blocking).  */
    if (fcntl(fd, F_SETLKW, &lock) == -1) {
        perror("fcntl");
        exit(1);
    }

    // 在文件中写入数据 NOTE: 关键区域
    // ...

    // 在写入数据完成后,我们再次使用fcntl函数来释放文件锁,使用F_SETLK标志表示释放锁。
    // # define F_RDLCK		0	/* Read lock.  */
    // # define F_WRLCK		1	/* Write lock.  */
    // # define F_UNLCK		2	/* Remove lock.  */
    // 根据手册来看,F_SETLKW 是阻塞式获取/释放锁,F_SETLK是非阻塞获取/释放锁
    lock.l_type = F_UNLCK;
    if (fcntl(fd, F_SETLK, &lock) == -1) {
        perror("fcntl");
        exit(1);
    }

    // 关闭文件
    close(fd);

    return 0;
}

根据手册阅读,如下:

在这里插入图片描述

只需要修改 lock.l_type = F_UNLCK; 就可以决定是上锁还是释放锁。F_SETLK 和 F_SETLKW 只是决定 阻塞/非阻塞 获取/释放 锁

我们做个实验看看,“写另外一个文件2,获取锁后不释放,文件1分别使用 阻塞/非阻塞 方式获取锁,看是否如手册所描述一般行为”

经过测试,当 Holding lock 的程序被强制退出时,它所持有的锁也会被强制释放

测试1:blocking 阻塞式获取锁

首先我们测试,先使用 norelease.c 文件获取锁,随后不退出

接着再使用 blocking.c 获取锁,可以发现会阻塞再这个地方

在这里插入图片描述

以下是 blocking.c 源码:
在这里插入图片描述
可以看到第36行的 printf 并没有被执行,blocking.c 验证完毕

测试2:nonblocking 非阻塞式获取锁

TODO:here

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1132730.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 网络巨型帧设置方法

1.指令设置 sudo ifconfig eth0 mtu 8192 2.修改系统文件 sudo vim /etc/dhcp/dhclient.conf

Linux创建临时文件mkstemp()tmpfile()

有些程序需要创建一些临时文件&#xff0c;仅供其在运行期间使用&#xff0c;程序终止后即行删除。 很多编译器程序会在编译过程中创建临时文件。GNU C 语言函数库为此而提供了一系列库函数。&#xff08;之所以有“一系列”的库函数&#xff0c;部分原因是由于这些函数分别继…

opencalib中lidar2camera安装记录

目录 一、opencalib安装 二、lidar2camera的安装 三、测试运行 四、出现过的问题 一、opencalib安装 代码地址&#xff1a;https://github.com/PJLab-ADG/SensorsCalibration/blob/master/README.md # pull docker image sudo docker pull scllovewkf/opencalib:v1 # Aft…

DBOW概要理解与记录

前言 DBOW作为一种视觉回环技术被广泛应用在各类VSLAM框架中&#xff0c;之前的经验主要集中在使用和抽象理解层面&#xff0c;近期花了一些时间仔细阅读了相关论文和源码&#xff0c;这里做一些记录。 两个关键概念 Vocabulary 通过预先训练得到的词汇库&#xff0c;以树状…

RISC-V架构——中断委托和中断注入

1、中断委托 1.1、中断委托的作用 &#xff08;1&#xff09;默认情况下&#xff0c;所有的陷入&#xff08;中断和异常&#xff09;都是在M模式下处理&#xff0c;然后再返回到发生陷入前的模式&#xff1b; &#xff08;2&#xff09;所有陷入都在M模式处理会涉及到模式切换…

Python 面向对象编程:类、对象、初始化和方法详解

Python 是一种面向对象的编程语言。在 Python 中&#xff0c;几乎所有东西都是对象&#xff0c;都具有其属性和方法。 类似于对象构造函数或用于创建对象的“蓝图”的类。 创建一个类 要创建一个类&#xff0c;请使用关键字 class&#xff1a; 示例&#xff0c;创建一个名为…

【数据结构】数组和字符串(三):特殊矩阵的压缩存储:三角矩阵、对称矩阵——一维数组

文章目录 4.2.1 矩阵的数组表示4.2.2 特殊矩阵的压缩存储a. 对角矩阵的压缩存储b. 三角矩阵的压缩存储结构体初始化元素设置元素获取打印矩阵主函数输出结果代码整合 c. 对称矩阵的压缩存储元素设置元素获取主函数输出结果代码整合 4.2.1 矩阵的数组表示 【数据结构】数组和字…

图像数据噪音种类以及Python生成对应噪音

前言 当涉及到图像处理和计算机视觉任务时&#xff0c;噪音是一个不可忽视的因素。噪音可以由多种因素引起&#xff0c;如传感器误差、通信干扰、环境光线变化等。这些噪音会导致图像质量下降&#xff0c;从而影响到后续的图像分析和处理过程。因此&#xff0c;对于从图像中获…

Thread同步问题,小案例

要求 有两个用户分别从同一个卡上取钱(总额&#xff1a;10000元)每次都取1000&#xff0c;当余额不足时&#xff0c;就不能取款了不能出现超取现象> 线程同步问题 public static void main(String[] args) {BankChoic bankChoic new BankChoic();Thread thread1 new Th…

设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)

初始化及打印函数 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #define MaxSize 10//定义最大长度 int InitArr[10] { 1,2,3,4,5,6,7,8,9,10 };typedef struct {int data[MaxSize];//用静态的数据存放数据元素int length;//顺序表当前长度 }Sqlist;//顺序表的类…

苹果将于8月31日举行今秋的第二场发布会

在今日凌晨&#xff0c;苹果宣布&#xff0c;将于北京时间10月31日早上8点举行今秋的第二场发布会&#xff0c;主题为“来势迅猛”。据多方猜测苹果本次活动的核心产品大概率是搭载全新M3芯片的Mac系列产品。 据了解&#xff0c;在苹果的产品线中&#xff0c;搭载M3芯片的Mac系…

C++ BinarySercahTree recursion version

for循环版本的&#xff1a;C BinarySercahTree for version-CSDN博客 Inorder()在c BinarySerschTree for verison写了。 还是按照那种嵌套的方式来写递归。 现在来写查找 FindR() bool FindR(){return _FindR(_root);}然后_FindR()函数写递归具体实现&#xff1a; 假设要…

HAL库 CubeMX STM32采用SDIO实现对SD卡和NAND Flash的读写

目录 一、选择合适的存储芯片。 可以去雷龙官网白嫖&#xff0c;白嫖链接&#xff1a;免费样品 二、SD卡/SD NAND底层原理 三、 CubeMX配置STM32具体步骤 1、时钟和系统配置 2、配置SDIO 3、配置DMA &#xff08;可选&#xff09; 4、设置串口 四、代码编写 1、公共…

vue 数据劫持代理原理

function lianxi(){// vue 数据劫持代理let data {username:curry,age:33}//模拟组件的实例let _this {}//利用Object.defineProperty()for( let item in data){//console.log(item,data[item])Object.defineProperty(_this,item,{//get:用来获取扩展属性值的,当获取该属性值…

基本指令(2):通配符,重定向,命令行管道

一、通配符 rm -rf ./* # * —— 通配符&#xff0c;指定路径下的所有文件&#xff08;不包括隐藏文件&#xff09;二、重定向 在理解重定向前&#xff0c;先要有一个概念&#xff1a;Linux下一切皆文件&#xff0c;大部分硬件设备都可以看做有读写方法&#xff0c;只不过有些方…

Web前端免费接入Microsoft Azure AI文本翻译,享每月2百万个字符的翻译

Azure 文本翻译是 Azure AI 翻译服务的一项基于云的 REST API 功能。 文本翻译 API 支持实时快速准确地进行源到目标文本翻译。 文本翻译软件开发工具包 (SDK) 是一组库和工具&#xff0c;可用于轻松地将文本翻译 REST API 功能集成到应用程序中。 文本翻译 SDK 可跨 C#/.NET、…

国腾GM8775C完全替代CS5518 MIPIDSI转2 PORT LVDS

集睿致远CS5518描述&#xff1a; CS5518是一款MIPI DSI输入、LVDS输出转换芯片。MIPI DSI 支持多达4个局域网&#xff0c;每条通道以最 大 1Gbps 的速度运行。LVDS支持18位或24位像素&#xff0c;25Mhz至154Mhz&#xff0c;采用VESA或JEIDA格 式。它只能使用单个1.8v电源&am…

人脸活体检测:Domain-Generalized Face Anti-Spoofing with Unknown Attacks

论文作者&#xff1a;Zong-Wei Hong,Yu-Chen Lin,Hsuan-Tung Liu,Yi-Ren Yeh,Chu-Song Chen 作者单位&#xff1a;National Taiwan University; E.SUN Financial Holding Co., Ltd.; National Kaohsiung Normal University 论文链接&#xff1a;http://arxiv.org/abs/2310.11…

Echarts多曲线数值与Y周刻度不符合

发现问题&#xff1a; 在展示多曲线图表的时候&#xff0c;发现图表曲线数值相差不大&#xff0c;但是图表展示的曲线相差很大&#xff0c;仔细观察之后发现是展示有问题(其实这并不能算是错误&#xff0c;只是由于忽略&#xff0c;导致的配置与预期不符合)。 问题复现&#x…

【低代码平台】JeecgBoot代码生成器如何使用?Online代码生成

Online代码生成 目前Vue3已经支持两种模式&#xff1a;Online在线模式 和 GUI模式代码生成。 JeecgBoot版本要求&#xff1a; 3.2.0 ( 提供了vue3、vue3Native模板目录 ) 第一步&#xff1a;通过online表单在线建表 jeecg提供了在线建表的功能&#xff0c;找到菜单&#xff1a;…