Linux -- 文件锁

本文介绍了文件锁的概念及其在多线程下载场景中的应用,通过lockf()函数实现文件的加锁和解锁,确保每个线程对文件的特定区域进行独立操作。在示例程序中,20个线程对同一文件内容加1,利用文件锁避免了竞争状态,保证了数据一致性。
摘要由CSDN通过智能技术生成

文件锁

文件锁:锁住整个文件或者锁住文件的一部分。

文件为什么要锁?
比如下载文件,一般是用多线程来实现的,那怎么才能确定每个线程操作的那一部分文件区域是被独立控制的,而没有同时被别人使用呢,我就可以使用文件锁。

下面的这些函数都能实现锁文件或者锁住文件的一部分。

fcntl();
lockf();
flock();

通过某个文件描述符对文件加锁反应到的是inode这个层面,而不是当前文件这个层面。因此指向这个文件的文件描述符是有可能对它造成意外解锁的。

inode结点可以看下链接: https://blog.csdn.net/xuechanba/article/details/119320211.

这里使用 lockf 这个函数来实现文件锁。

#include <unistd.h>
int lockf(int fd, int cmd, off_t len);

我要对它实现的cmd命令:

F_LOCK

F_LOCK为文件指定的部分设置排他锁。如果这个部分已经被锁定,调用将阻塞,直到前一个锁被释放。如果此节与之前的锁定节重叠,则将两者合并。当持有锁的进程关闭文件的某些文件描述符时,文件锁就被释放。子进程不会继承这些锁。

F_ULOCK

Unlock the indicated(指定的) section of the file.  

看第三个参数len

and  if  len is zero, the section extends from the current file position to infinity, encompassing the present and future end-of-file positions.

如果len为0,该section将从当前文件位置扩展到无限,包括当前和将来的文件结束位置。

看返回值

RETURN VALUE
On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

需求:
文件中的内容为1,创建20个线程,每个线程都对读到的内容进行加1操作。在操作过程中,为了避免竞争,使用文件锁。

程序:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

#define PROCNUM   20
#define FNAME    "/work/thread_code/filelock/test"
#define LINESIZE 1024

void func_add()
{
    int fd;
    FILE *fp;
    char linebuf[LINESIZE];

    fp = fopen(FNAME,"r+");
    if(fp == NULL)
    {
        perror("fopen()");
        exit(1);
    }

    //将fp流中的文件描述符fd给挑出来
    //file流中一定有一个文件描述符
    fd = fileno(fp);

    //锁多长不确定,因为有时候文件长度是会变化的
    lockf(fd,F_LOCK,0);
    fgets(linebuf,LINESIZE,fp);
    fseek(fp,0,SEEK_SET);//文件内指针定位

    //用来放大故障
    sleep(1);

 	//加1再写回去
    fprintf(fp,"%d\n",atoi(linebuf)+1);

    //因为文件是全缓存模式,而fprintf是行缓存模式
    //有可能出现写不进去的情况,所以要加一个刷新流的操作
    fflush(fp);

    //防止其他指向该文件的文件描述符意外解锁
    lockf(fd,F_ULOCK,0);

    fclose(fp);

    return;
}

int main()
{
    pid_t pid;

    int i;

    for(i=0;i<PROCNUM;i++)
    {
        pid = fork();
        if(pid < 0)
        {
            perror("fork()");
            exit(1);
        }

        if(pid == 0)
        {
            func_add();
            exit(0);
        }
    }

    for(i=0;i<PROCNUM;i++)
    {
        wait(NULL);
    }
    
	return 0;
}

运行程序,等待超过20秒之后。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xuechanba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值