zoukankan      html  css  js  c++  java
  • 文件加锁,作用是用来做什么?以及使用细节

     https://www.cnblogs.com/chenwenbiao/archive/2011/08/01/2123905.html

    demo.php

     <?php
     $fp = fopen("file_lock.txt", "w");
     //加锁
     if (flock($fp, LOCK_EX)) {
       fwrite($fp, "abc
    ");
       sleep(10);
       fwrite($fp, "ddd
    ");
       echo 1;
       //执行完成解锁
       flock($fp, LOCK_UN);
     }
     // 关闭文件
     fclose($fp);
                                                                                     
                                                                                     
    

      lock.go

    package main
    
    import (
      "syscall"
      "os"
      "log"
      "time"
    )
    
    func main() {
      f, err := os.OpenFile("file_lock.txt", os.O_RDWR, 0777) 
      if err != nil {
        log.Println("open file err:", err)
      }
      for {
        err = syscall.Flock(int(f.Fd()), syscall.LOCK_SH|syscall.LOCK_NB)
        if err != nil {
          log.Println("flock err:", err)
          log.Println("flock err:", syscall.EWOULDBLOCK )
        } else {
          log.Println("lock success")
          return
        }
        time.Sleep(time.Second)
      }
    
    }
                                           
                                           
    

      开窗口一执行: php demo.php

      开窗口二执行: go  lock.go

    -------------------------------

    bool flock ( int handle, int operation [, int &wouldblock] );
    flock() 操作的 handle 必须是一个已经打开的文件指针。operation 可以是以下值之一:

    1. 要取得共享锁定(读取程序),将 operation 设为 LOCK_SH(PHP 4.0.1 以前的版本设置为 1)
    2. 要取得独占锁定(写入程序),将 operation 设为 LOCK_EX(PHP 4.0.1 以前的版本中设置为 2)
    3. 要释放锁定(无论共享或独占),将 operation 设为 LOCK_UN(PHP 4.0.1 以前的版本中设置为 3)
    4. 如果你不希望 flock() 在锁定时堵塞,则给 operation 加上 LOCK_NB(PHP 4.0.1 以前的版本中设置为 4)

    建两个文件
    (1) a.php

    $file = "temp.txt";   
    $fp = fopen($file , 'w');   
    if(flock($fp , LOCK_EX)){   
         fwrite($fp , "abc ");   
         sleep(10);   
         fwrite($fp , "123 ");   
        flock($fp , LOCK_UN);   
    }   
    fclose($fp);  

    (2) b.php

    $file = "temp.txt";   
    $fp = fopen($file , 'r');   
    echo fread($fp , 100);   
    fclose($fp);  

    运行 a.php 后,马上运行 b.php ,可以看到输出:
    abc
    等 a.php 运行完后运行 b.php ,可以看到输出:
    abc
    123
    显然,当 a.php 写文件时数据太大,导致时间比较长时,这时 b.php 读取数据不完整

    修改 b.php 为:

    $file = "temp.txt";   
    $fp = fopen($file , 'r');   
    if(flock($fp , LOCK_EX)){   
        echo fread($fp , 100);   
        flock($fp , LOCK_UN);   
    } else{   
        echo "Lock file failed... ";   
    }   
    fclose($fp);  

    运行 a.php 后,马上运行 b.php ,可以发现 b.php 会等到 a.php 运行完成后(即 10 秒后)才显示:
    abc
    123
    读取数据完整,但时间过长,他要等待写锁释放。

    修改 b.php 为:

    $file = "temp.txt";   
    $fp = fopen($file , 'r');   
    if(flock($fp , LOCK_SH | LOCK_NB)){   
        echo fread($fp , 100);   
        flock($fp , LOCK_UN);   
    } else{   
        echo "Lock file failed... ";   
    }   
    fclose($fp);  

    运行 a.php 后,马上运行 b.php ,可以看到输出:
    Lock file failed…
    证明可以返回锁文件失败状态,而不是向上面一样要等很久。

    结论:
    建议作文件缓存时,选好相关的锁,不然可能导致读取数据不完整,或重复写入数据。
    file_get_contents 好像选择不了锁,不知道他默认用的什么锁,反正和不锁得到的输出一样,是不完整的数据。
    我是要做文件缓存,所以只需要知道是否有写锁存在即可,有的话就查数据库就可以了。
    测试环境:Linux(Ubuntu 6) , PHP 5.1.2 , Apache 2

    再转:

    文件锁有两种:共享锁和排他锁,也就是读锁(LOCK_SH)和写锁(LOCK_EX) 
    文件的锁一般这么使用:
    1. $fp = fopen("filename", "a");   
    2. flock($fp, LOCK_SH) or die("lock error")   
    3. $str = fread($fp, 1024);   
    4. flock($fp, LOCK_UN);   
    5. fclose($fp);  

    注意fwrite之后,文件立即就被更新了,而不是等fwrite然后fclose之后文件才会更新,这个可以通过在fwrite之后fclose之前读取这个文件进行检查 

    但是什么时候使用lock_ex什么时候使用lock_sh呢? 

    读的时候: 
    如果不想出现dirty数据,那么最好使用lock_sh共享锁。可以考虑以下三种情况: 
    1. 如果读的时候没有加共享锁,那么其他程序要写的话(不管这个写是加锁还是不加锁)都会立即写成功。如果正好读了一半,然后被其他程序给写了,那么读的后一半就有可能跟前一半对不上(前一半是修改前的,后一半是修改后的) 
    2. 如果读的时候加上了共享锁(因为只是读,没有必要使用排他锁),这个时候,其他程序开始写,这个写程序没有使用锁,那么写程序会直接修改这个文件,也会导致前面一样的问题 
    3. 最理想的情况是,读的时候加锁(lock_sh),写的时候也进行加锁(lock_ex),这样写程序会等着读程序完成之后才进行操作,而不会出现贸然操作的情况 

    写的时候: 
    如果多个写程序不加锁同时对文件进行操作,那么最后的数据有可能一部分是a程序写的,一部分是b程序写的 
    如果写的时候加锁了,这个时候有其他的程序来读,那么他会读到什么东西呢? 
    1. 如果读程序没有申请共享锁,那么他会读到dirty的数据。比如写程序要写a,b,c三部分,写完a,这时候读读到的是a,继续写b,这时候读读到的是ab,然后写c,这时候读到的是abc. 
    2. 如果读程序在之前申请了共享锁,那么读程序会等写程序将abc写完并释放锁之后才进行读。 

    还有一篇也写得不错的博文:

    http://hxsdit.com/1110

    -------------------------------

    File locking in Linux

    29 Jul 2016

    Table of contents


    Introduction

    File locking is a mutual-exclusion mechanism for files. Linux supports two major kinds of file locks:

    • advisory locks
    • mandatory locks

    Below we discuss all lock types available in POSIX and Linux and provide usage examples.


    Advisory locking

    Traditionally, locks are advisory in Unix. They work only when a process explicitly acquires and releases locks, and are ignored if a process is not aware of locks.

    There are several types of advisory locks available in Linux:

    • BSD locks (flock)
    • POSIX record locks (fcntl, lockf)
    • Open file description locks (fcntl)

    All locks except the lockf function are reader-writer locks, i.e. support exclusive and shared modes.

    Note that flockfile and friends have nothing to do with the file locks. They manage internal mutex of the FILE object from stdio.

    Reference:

    Common features

    The following features are common for locks of all types:

    • All locks support blocking and non-blocking operations.
    • Locks are allowed only on files, but not directories.
    • Locks are automatically removed when the process exits or terminates. It’s guaranteed that if a lock is acquired, the process acquiring the lock is still alive.

    Differing features

    This table summarizes the difference between the lock types. A more detailed description and usage examples are provided below.

     BSD lockslockf functionPOSIX record locksOpen file description locks
    Portability widely available POSIX (XSI) POSIX (base standard) Linux 3.15+
    Associated with File object [i-node, pid] pair [i-node, pid] pair File object
    Applying to byte range no yes yes yes
    Support exclusive and shared modes yes no yes yes
    Atomic mode switch no - yes yes
    Works on NFS (Linux) Linux 2.6.12+ yes yes yes

    File descriptors and i-nodes

    file descriptor is an index in the per-process file descriptor table (in the left of the picture). Each file descriptor table entry contains a reference to a file object, stored in the file table (in the middle of the picture). Each file object contains a reference to an i-node, stored in the i-node table (in the right of the picture).

    A file descriptor is just a number that is used to refer a file object from the user space. A file object represents an opened file. It contains things likes current read/write offset, non-blocking flag and another non-persistent state. An i-node represents a filesystem object. It contains things like file meta-information (e.g. owner and permissions) and references to data blocks.

    File descriptors created by several open() calls for the same file path point to different file objects, but these file objects point to the same i-node. Duplicated file descriptors created by dup2() or fork() point to the same file object.

    A BSD lock and an Open file description lock is associated with a file object, while a POSIX record lock is associated with an [i-node, pid] pair. We’ll discuss it below.

  • 相关阅读:
    通过指定的“虚拟路径”返回路径下“文件名列表”
    ASP.NET Session丢失问题原因及解决方案
    纯CSS打造Bubble气泡提示框
    分享几个超级震憾的图片特效
    有了jQuery.Jcrop,选取美女的哪个部位你说了算
    jQueryTranslator调用Google翻译实例及源码【译】
    轻松学习正则表达式【译】
    Android系统源代码情景分析:基础知识
    HTML5斯诺克桌球俱乐部【译】
    ASP.NET中使用V3版本的Google Maps API【译】
  • 原文地址:https://www.cnblogs.com/oxspirt/p/14705345.html
Copyright © 2011-2022 走看看