美文网首页
文件I/O和记录锁

文件I/O和记录锁

作者: 食梦狸猫 | 来源:发表于2019-05-08 18:37 被阅读0次

文件描述符:

文件描述符是一个非负整数,所有打开的文件都通过文件描述符引用。
按照惯例:0(STDIN_FILENO)与进程的标准输入关联,1(STDOUT_FILENO)与标准输出关联,2(STDERR_FILENO)与标准错误输出关联。

文件偏移量

每个打开的文件都有一个与其关联的“当前文件偏移量”,用以度量从文件开始处计算的字节数。当打开一个文件时,除非指定O_APPEND,否则偏移量设置为0。lseek仅将当前的文件偏移量记录在内核中,不引起任何I/O操作,然后偏移量用于下一次读或者写。

空洞

文件偏移量大于文件的长度,在下一次对该文件的写中将加长该文件,并在文件中构成一个空洞。位于文件中没有写过的字节都为0

原子操作

任何一个需要多个函数调用的操作都不是原子操作,因为在多个函数调用之间,内核可能会临时挂起进程,这时若有其他的进程对同一个文件进行操作就会造成不可预知的后果。
原子操作:是由多步组成的操作,要么执行完全部的步骤,要么一步都不执行。
unix系统提供的原子操作:

ssize_t pread(int fileds, void* buf, size_t nbytes,off_t offset);

size_t pwrite(int fileds, const void* buf, size_t bytes, off_t offset);

sync,fsync,fdatasync

  • 延迟写:数据写入文件时,内核先是将数据复制到一个缓冲区中,如果缓冲区未被写满,则等待其写满或内核需要重用该缓冲区时才将该缓冲区排入输出队列,待其到达队首,才进行实际的I/O操作。

延迟写减少了磁盘读写次数,但也降低了内容跟新速度。当系统发生故障时,延迟写可能会造成文件更新内容的丢失。

为了保证文件系统和缓冲区中内容的一致性:

  • sync()
    将所有修改过的块缓冲区排入写队列,然后马上返回。
  • fsync(int fd)
    只对fd指定的文件起作用,并等待写操作结束。同时还会更新文件的属性
  • fdatasync(int fd)
    和fsync类似,但不会影响文件属性,只影响文件的数据部分。

记录锁

若有时两个进程一起同时编辑某个文件,那么文件的状态将取决于写该文件的最后一个进程。

fcntl记录锁

int fcntl(int fd, int cmd, ....);
....

struct flock
{
  short l_type;
//锁类型:F_RDLCK(共享读锁),F_WRLCK(独占写锁),F_UNLCK(解锁一个区域)
  off_t l_start;
  short l_whence;
//加锁或者解锁区域的起始字节偏移量
  off_t l_len;
//区域字节长度,若为0,则表示锁的区域从其起点开始直到最大可能偏移量为止
  pid_t l_pid;
//持有进程的ID
}

//为了锁整个文件,可以设置l_start和l_whence,使锁的起点在文件起始处,并且l_len为0。

共享读锁:多个进程在一个给定的字节上可以有一把共享的读锁。

独占写锁:在一个给定字节上只能由一个进程独占的一把写锁。

如果在一个给定字节上已经有一把或者多把读锁,则不能在该字节上再加写锁。

如果在一个字节上已经有一把独占性的写锁,则不能再加任何读锁。

加读锁时,文件描述符必须读打开。
加写锁时,文件描述符必须写打开。

fcntl函数的三个命令:

  • F_GETLK
    判断flockptr所描述的锁是否会被另外的一把锁所阻塞。

  • F_SETLK
    设置由flockptr所描述的锁。若不允许,则出错返回。

  • F_SETLKW
    F_SETLK的阻塞版本

死锁

如果两个进程相互等待对方持有并且锁定的资源时,则这两个进程就处于死锁状态。检测到死锁时,内核必须选择一个进程接收出错返回。

锁的隐含继承和释放

  • 当一个进程终止时,它所建立的锁全部释放。

  • 当进程关闭一个文件描述符时,该进程通过该描述符引用的文件上的锁都会被释放。

  • 由fork产生的子进程不继承父进程所设置的锁。

  • 在执行exec后,新程序可以继承原执行程序的锁。

守护进程用文件锁加锁,可以保证只有唯一的一个该进程。

int lockfile(int fd)
{
    struct flock f1;

    f1.l_type = F_WRLCK;
    f1.l_start = 0;
    f1.l_whence = SEEK_SET;
    f1.l_len = 0;
    return(fcntl(fd,F_SETLK,&f1));
}

在文件尾端加锁

建议性锁和强制性锁

相关文章

  • 文件I/O和记录锁

    文件描述符: 文件描述符是一个非负整数,所有打开的文件都通过文件描述符引用。按照惯例:0(STDIN_FILENO...

  • APUE读书笔记-14高级输入输出(1)

    1、简介 这一章描述了大量的函数和内容,它们涉及到高级的I/O操作:非阻塞I/O,记录锁,System V流,多I...

  • UNIX 文件I/O

    UNIX 文件I/O 引言 介绍UNIX系统可用的文件I/O函数---打开文件、读文件、写文件等 UNIX文件I/...

  • Linux性能优化实战——磁盘I/O调优

    前言 本文基于文件系统和磁盘I/O工作原理,通过典型I/O问题分析,总结磁盘I/O调优的一般套路。 问题描述:文件...

  • I/O优化

    I/O基本知识 整个I/O操作由应用程序、文件系统和磁盘共同完成,应用程序将I/O命令发送到文件系统,文件系统在合...

  • 异步I/O—事件循环机制

    I/O简介 1.I/O操作:内核在进行文件I/O操作时,通过文件描述符(fd:一个整数—应用程序和内核之间的凭证)...

  • 17.Java中的IO

    1.I/O操作的目标 2.I/O的分类方法 3.读取文件和写入文件的方法 I/O操作的目标 从数据源当中读取数据,...

  • linux系统API,c,c++的标准I/O和文件I/O

    标准I/O:数据从内存与标准i/o设备(stdio,stdout,stderr)之间的数据流动 文件I/O:文件的...

  • C语言学习12.文件和IO

    I/O:input/output,输入输出。分三类:标准I/O,串I/O,文件I/O 标准I/O: 标准输入:从标...

  • Python文件操作

    文件I/O I 输入(input) O输出(Output) 文件操作步骤:1.打开文件 2.读写文件 3...

网友评论

      本文标题:文件I/O和记录锁

      本文链接:https://www.haomeiwen.com/subject/uixvoqtx.html