Linux中文件执行中的锁定怪现象解释

   本来今天不准备开电脑了,太困了,想睡觉,然而一哥们儿短信都发过来了,要问个问题,于是还是打开了电脑,没想到是一个很有代表性的问题,顺便也牵扯了前些天我的工作中的一个bug,值得记录下来。问题如下:

  linux下,一个可执行文件exe1正在执行中,rm –f可以将其删除,mv可以将其移除,mv $other exe1也可以将其替换,但是cp $other exe1则显示文件忙,求解。

  这实际上并不是一个真正的问题,因为只要你的基础知识扎实,这个问题显然很简单,原因只有一个,那就是linux文件基于引用计数。现在问题是这些个命令如何来操作一个文件的引用计数。下面的讨论都是基于独占打开的模式。

  如果一个文件已经被打开,那么它的引用计数会增加1,如果调用了rm,实际上底层只是unlink了一下,也就是说将它的引用计数减少1,这样虽然你在界面上(命令行或者GUI)看不到它了,但是它被打开时的计数还在,只有当它被关闭的时候,引用计数变为0,才彻底删除它。

  再说mv命令,它实际上只是一个源文件的rename而已,如果mv的目标本来就存在,那么在目标上执行一个类似rm的效果,也就是unlink一下,结合引用计数的理论,目标文件如果已经被打开,那么当关闭的时候将不复存在,如果本来就没有被打开,那么mv的时候,目标直接被删除,因为unlink之后,它的引用计数变成了0。

  最后看一下cp命令,cp的话并不触动源文件和目标文件元数据本身(时间戳除外),它只是打开源文件和目标文件,在源文件上执行read,然后将结果write到目标文件,实质上是一个IO操作,对于可执行文件,是独占打开的,并不允许写入,因此会出错。

  这里就不再列出内核源码了,可以自行参考系统调用的实现而加深理解,不过最好别干巴巴的看,还是结合strace以及objdump比较好,要知道是怎么以及什么时候调用的,以及调用参数是什么,否则就和八股文没区别了。那么这和我工作中的bug有什么关系呢?这个bug源于OpenVPN的日志记录,并且配置了日志回滚,回滚配置文件关键字段如下:

  size 4M

  missingok

  rotate 9

  compress

  delaycompress

  create 644 xx xx

  …

  结果当日志回滚成了vpn.log.1之后,这个vpn.log.1依然继续被写入。这个原因正是rename造成的。在logrotate的man页面中,有一个copytruncate配置,其含义就是不进行rename,而只是copy,然后将原来的文件truncate,加入这个就可以了。

  千万不要小看这些很简单的命令,真正理解的人并不多,即使真正的理解,出现问题,能真正对应到原理也不多,很简单的东西如果能彻底做到透彻的理解并且活用,再往深入学习才是有意义的。

时间: 2024-11-02 04:15:02

Linux中文件执行中的锁定怪现象解释的相关文章

Linux中文件执行中的锁定的怪现象

  本来今天不准备开电脑了,太困了,想睡觉,然而一哥们儿短信都发过来了,要问个问题,于是还是打开了电脑,没想到是一个很有代表性的问题,顺便也牵扯了前些天我的工作中的一个bug,值得记录下来.问题如下: linux下,一个可执行文件exe1正在执行中,rm –f可以将其删除,mv可以将其移除,mv $other exe1也可以将其替换,但是cp $other exe1则显示文件忙,求解. 这实际上并不是一个真正的问题,因为只要你的基础知识扎实,这个问题显然很简单,原因只有一个,那就是linux文件

Linux系统中查看执行中的进程占用内存量的方法

Linux中查看某个进程占用内存的情况,执行如下命令即可,将其中的[pid]替换成相应进程的PID号: 代码如下: cat /proc/[pid]/status 说明 /proc/[pid]/status中所保存的信息除了内存信息,还包括进程IDs.信号等信息,此处暂时只介绍内存相关的信息. 字段                 说明 VmPeak        进程所使用的虚拟内存的峰值 VmSize         进程当前使用的虚拟内存的大小 VmLck          已经锁住的物理内

.NET中获取Access新增记录Id怪现象解决方法_实用技巧

复制代码 代码如下: using System; using System.Data.OleDb; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine(GetUserId("dnawo")); Console.ReadKey(); } /// <summary> /// 获取用户Id /// </summary> /

c#菜单中隐藏之后上下滚动出现怪现象

问题描述 vs2005开发语言c#菜单列表中有一个是隐藏的visible=false,然后用方向键上下滚动菜单的话,会出现多余出来的空白,怎么解决?比如,菜单test中有a,b,c,d,e,f隐藏e(e.visible=false)然后上下滚动,出现下面的空白 解决方案 解决方案二:没明白我试了下不会出现e的空白解决方案三:像这样吗?解决方案四:不知道怎么贴图比如原来菜单隐藏e焦点在a上用上方向键testtesttestaagbb空白cc空白dd空白ef空白fg空白g解决方案五:用的是menuS

Access数据库操作中出现的怪现象

我用的数据库是Access2000的,系统为Win2000 Advance Server.今天在程序调试中遇到了以下几个怪现象: 1.如果Access程序把调试的程序处于打开状态时(不一定是改表或表结构的界面),程序中把response.buffer设为true,则程序在用Update更 新时老是说找不到数据.当Access关闭时又正常了. 2.如果一个文件什么都没输出,而把response.buffer设为true,而此时Access也没有把此数据库处于打开状态,但程序在用Update时仍说没

Linux中误删除了某个文件后从进程相关的文件描述中恢复数据

在Linux中误删除了某个文件,但是 ps-ef|grep 文件名 发现某个进程还在使用该文件,那么可以通 过以下方式恢复文件. 例如: 创建一个简单文件/tmp/test.txt, 随便向里面写点内容 两个client模拟,client1 负责打开文件less /tmp/test.txt(模拟占用线程) client2 负责恢复文件 恢复步骤(均在client2上执行) 1. 查看/tmp/test.txt被占用的进程id [root@host tmp]# ps -ef|grep test.t

Linux 从进程相关的文件描述中恢复数据

 在Linux中误删除了某个文件,但是 ps-ef|grep 文件名 发现某个进程还在使用该文件,那么可以通 过以下方式恢复文件. 例如: 创建一个简单文件/tmp/test.txt, 随便向里面写点内容 两个client模拟,client1 负责打开文件less /tmp/test.txt(模拟占用线程) client2 负责恢复文件 恢复步骤(均在client2上执行) 1. 查看/tmp/test.txt被占用的进程id [root@host tmp]# ps -ef|grep test.

linux中文件操作命令(创建、删除、查看、权限设置)

创建文件(touch)命令 Linux 创建文件命令主要用到的是 touch 命令,touch 命令可用来修改文件的访问时间,修改时间,如果没有指定时间,则默认为当前时间,如果指定的文件不存在,则 touch 命令将创建该文件. 命令格式: touch [-acfm] [-r file(参照文件)] [-t decimtime(时间值)] [-d time(时间值)] [--time={atime,access,use,mtime,modify}] [--date=time] [--refere

Linux中文件权限目录权限的意义及权限对文件目录的意义_linux shell

linux中目录与文件权限的意义 一.文件权限的意义 r:可以读这个文件的具体内容: w:可以编辑这个文件的内容,包括增加删除文件的具体内容: x:文件就具有了可执行的权限-------注意:这里和window不一样,在win中,文件的可执行权限是通过扩展名表现出来的,如exe.bat等,但是在linux中文件的可执行权限是通过这个x决定的,与文件名没有什么关系. 二.目录权限的意义 r:可以查看此目录下的完整文件列表信息. w:可以对此目录下的所有的文件及目录进行相关的更改,也就是可以更改这个