close和unlink。以前时候总是不太理解两者的区别,最近看到一篇博客比较详细地描述了二者的本质区别,这里我引用了它的原文。
“每一个文件,都可以通过一个struct stat的结构体来获得文件信息,其中一个成员st_nlink代表文件的链接数。当通过shell的touch命令或者在程序中open一个带有O_CREAT的不存在的文件时,文件的链接数为1。
通常open一个已存在的文件不会影响文件的链接数。open的作用只是使调用进程与文件之间建立一种访问关系,即open之后返回fd,调用进程可以通过fd来read 、write 、 ftruncate等等一系列对文件的操作。
close()就是消除这种调用进程与文件之间的访问关系。自然,不会影响文件的链接数。在调用close时,内核会检查打开该文件的进程数,如果此数为0,进一步检查文件的链接数,如果这个数也为0,那么就删除文件内容。
link函数创建一个新目录项,并且增加一个链接数
unlink函数删除目录项,并且减少一个链接数。如果链接数达到0并且没有任何进程打开该文件,该文件内容才被真正删除。如果在unlilnk之前没有close,那么依旧可以访问文件内容。
综上所诉,真正影响链接数的操作是link、unlink以及open的创建。
删除文件内容的真正含义是文件的链接数为0,而这个操作的本质完成者是unlink。close能够实施删除文件内容的操作,必定是因为在close之前有一个unlink操作。”

UNIX文件系统包括引导块、超级块、i节点区、文件存储区、进程对换区等几部分。
引导块占用第0号物理块,不属于文件系统管辖,如果系统中有多个文件系统,只有根文件系统才有引导程序放在引导块中,其余文件系统都不使用引导块。
超级块占用第1号物理块,是文件系统的控制块,超级块包括:文件系统的大小、空闲块数目、空闲块索引表、空闲i节点数目、空闲i节点索引表、封锁标记等。超级块是文件系统为文件分配存储空间、回收存储空间的依据。
i节点区存放i节点,i节点是对文件进行控制和管理的一种数据结构。
文件存储区是存放文件内容的区域,文件存储区中各数据块的使用情况在超级中有记录,系统利用超级块中的记录完成对数据块的分配和回收。
unix文件系统中很重要的概念之一就是i节点,下面就开始说说这个重要的概念。
每一个文件都由自己的i节点,每个i节点都有唯一的i节点号。
i节点的结构如下(参考/usr/include/sys/ino.h)
struct dinode
{
ushort  di_mode;//文件类型与权限
short   di_nlink;
ushort di_uid;
ushort di_gid;
off_t  di_size;
char di_addr[40];
time_t di_atime;
time_t di_mtime;
time_t di_ctime;
}
从上面的结构中可以看出:
1、i节点保存了文件的属性和类型、存放文件内容的物理块地址、最近一次的存取时间、最后一次修改时间、创建此文件的时间。
2、i节点中没有记录文件名字,那么文件的名字是怎么关联到i节点的呢?这么设计又有什么好处呢?
     在linux系统中,文件的查找不是通过文件名称来查找的。实际上是通过i节点来实现文件的查找定位的。我们可以形象的将i节点看作是一个指针。当文件存储到磁盘上去的时候,文件肯定会存放到一个磁盘位置上,可以这样想象,既然文件数据是存放在磁盘上的,如果我们知道这个文件数据的地址,当我们想读写文件的时候,我们是不是直接使用这个地址去找到文件就可以了呢?
     是的,在linux下,i节点其实就是可以这么认为,把i节点看作是一个指向磁盘上该文件存储区的地址。只不过这个地址我们一般没办法直接使用,而是通过文件名来间接使用的。事实上,i节点不仅包含了文件数据存储区的地址,上面也提到过,它还包含了很多其他信息(文件的属性和类型,存放文件内容的物理块地址,最近一次的存取时间,最近一次的修改时间,创建文件的时间)。但是i节点是不保存文件名的。文件名保存在一个目录项中。每个目录项中都包含了文件名和i节点。回到正题,i节点中没有记录文件爱你名字,那么文件按名是怎么关联到i节点的呢。这里就关系到了硬链接与符号链接的区别。
如下图:

       对于硬链接来说,如果删掉源文件helloA.c,那么磁盘上数据文件按是不会被删除的。因为i节点上记录了该文件的硬链接数。只有硬链接数为0的时候,删除文件名的时候,该数据在磁盘上才会删除。
       所谓的符号链接,其实是指文件索引的索引。当源文件helloB.c删除之后,其实磁盘数据文件还在,helloC.c也无法使用。符号链接包含了一个文件名的路径,如果这个文件名被删除,这个符号链接自然就不能正常工作了。
3、di_mode这个是怎么保存文件类型+用户权限的呢?
比如:
drwxr-xr-x         7         root            sys              512      dec  15   2012   var
 -rw-r--r---         1         root            sys              4003     Ju1 4 23 : 37      1
红色字体部分说明是文件类型标记和文件权限,这个字符串跟ushort di_mode怎么关联的?
ushort di_mode是16位2进制数,保存的就是文件类型及用户权限信息,具体结构如下:
4                  8                    12                    16
第1-4位:文件类型
第5位:suid位
第6位:sgid位
第7位:sticky位
第8-10位:文件属主权限位
第11-13位:文件属组权限位
第14-16位:其他用户权限位
1)文件类型分类:
d--目录文件、f--普通文件、b--块设备文件、c--字符设备文件、l--链接文件
2)文件类型位算法
从系统的头文件/usr/include/sys/stat.h中可以知道:
a、#define   S_IFMT   0170000 -- 文件类型掩码宏,0170000以0开头,表示这是一个8进制数,转换成2进制,正好是 1 111 000 000 000 000 ,高4位全置1;
b、#define   S_IFREG 0100000 -- 普通文件类型掩码,0100000,转换成2进制,1 000 000 000 000 000,最高位置1;
c、#define S_ISREG(m)   (((m) & S_IFMT) == S_IFREG) --   判断文件是否普通文件的宏函数
举例说明:m值即为我们取到ushort di_mode,假设其2进制值为 0 011 000 000 000 000,对应的8进制为 060000   。S_ISREG(0060000) 即 (((0060000) & 0170000 ) == 0100000) ,该值返回False,则代表该文件不是普通文件。

说明:stat结构中的大多数信息都取自i节点。只有两项数据存放在目录项中:文件名和i节点编号。i节点编号的数据类型是ino_t。
注意:每个文件系统各自对它们的i节点进行编号,因此目录项中的i节点编号数指向同一文件系统中相应的i节点,不能使一个目录项指向另一个文件系统的i节点。
讨论linux中link,unlink,close,fclose函数对st_nlink的影响
     linux中每一个文件,都可以通过一个struct stat的结构体来获得文件信息,其中一个成员st_nlink代表文件的链接数。
       当通过shell的touch命令或者在程序中open一个带有O_CREAT的不存在的文件时,文件的链接数为1。
       通常open一个已存在的文件不会影响文件的链接数。open的作用只是使调用进程与文件之间建立一种访问关系,即open之后返回fd,调用进程可以通过fd来read 、write 、 ftruncate等等一系列对文件的操作。
       close()就是消除这种调用进程与文件之间的访问关系。自然,不会影响文件的链接数。在调用close时,内核会检查打开该文件的进程数,如果此数为0,进一步检查文件的链接数,如果这个数也为0,那么就删除文件内容。
       link函数创建一个新目录项,并且增加一个链接数。
       unlink函数删除目录项,并且减少一个链接数。如果链接数达到0并且没有任何进程打开该文件,该文件内容才被真正删除。如果在unlilnk之前没有close,那么依旧可以访问文件内容。
       综上所诉,真正影响链接数的操作是link、unlink以及open的创建。
       删除文件内容的真正含义是文件的链接数为0,而这个操作的本质完成者是unlink。close能够实施删除文件内容的操作,必定是因为在close之前有一个unlink操作。
       举个例子简单说明:通过shell   touch test.txt
  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <sys/stat.h>
  4 #include <sys/types.h>
  5 #include <fcntl.h>
  6
  7 int main(int argc,char *argv[])
  8 {
  9     struct stat buf;
 10     stat("test.txt",&buf);
 11     printf("1.link=%d\n",buf.st_nlink);
 12
 13 int fd;
 14 fd = open("test.txt",O_RDONLY);
 15 stat("test.txt",&buf);
 16 printf("2.link=%d\n",buf.st_nlink);
 17
 18     close(fd);
 19     stat("test.txt",&buf);
 20     printf("3.link=%d\n",buf.st_nlink);
 21 link("test.txt","test2.txt");
 22 stat("test.txt",&buf);
 23 printf("4.link=%d\n",buf.st_nlink);
 24     unlink("test2.txt");
 25     stat("test.txt",&buf);
 26     printf("5.link=%d\n",buf.st_nlink);
 27 fd = open("test.txt",O_RDONLY);
 28 stat("test.txt",&buf);
 29 printf("6.link=%d\n",buf.st_nlink);
 30     unlink("test.txt");
 31     fstat(fd,&buf);
 32     printf("7.link=%d\n",buf.st_nlink);
 33
 34     return 0;
 35
 36 }
顺次执行以上8个步骤,结果如下:
1.link=1
2.link=1    //open不影响链接数
3.link=1    //close不影响链接数
4.link=2    //link之后链接数加1
5.link=1    //unlink后链接数减1
6.link=1    //重新打开  链接数不变
7.link=0    //unlink之后再减1,此处我们改用fstat函数而非stat,因为unlilnk已经删除文件名,所以不可以通过   文件名访问,但是fd仍然是打开着的,文件内容还没有被真正删除,依旧可以使用fd获得文件信息。
执行步骤8,文件内容被删除....
注意:在第步骤6中,文件test.txt此时已经打开并没有将其关闭,而步骤七中直接将其释放,此时,文件的内容没有真正的被删除。进程任然可以继续读文件中的内容。直到关闭该文件或进程结束自动关闭后,内核首先会先检查打开文件的进程数,如果为0,然后内核检查其链接数,由于在第七步中已经释放了最后一个,所以其链接数为0,那么就删除该文件的内容。
下图是抄之apue的精典例子:

unlink的这种性质经常被程序用来确保即使是在该程序崩溃时,它所创建的临时文件也不会被遗留下来。进程用open或creat创建一个文件,然后立即调用unlink。因为该文件仍旧是打开的,所以不会将其内容删除。只有当进程关闭该文件或终止时(这种情况下,内核会关闭该进程打开的全部文件),该文件的内容才会被删除。
    unlink删除该符号链接,而不是删除由该链接所引用的文件。给出符号链接名的情况下,没有一个函数能删除由该链接所引用的文件。

unlink与close关系相关推荐

  1. HTTP协议通信原理 (资源)

    2019独角兽企业重金招聘Python工程师标准>>> 了解HTTP HTTP(HyperText Transfer Protocol)是一套计算机通过网络进行通信的规则.计算机专家 ...

  2. HTTP请求方法对照表(15种全部解释)

    HTTP Request Method共计15种 序号 方法 描述 1 GET 请求指定的页面信息,并返回实体主体. 2 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 3 ...

  3. 网络(7)-HTTP(HyperText Transfer Protocol,超文本传输协议)

    http是一个简单的请求-响应协议,它通常运行在TCP之上.它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应.请求和响应消息的头以ASCII码形式给出:而消息内容则具有一个类似MIME的 ...

  4. Django:视图装饰器

    客户端对服务器发起的HTTP请求时,并不是所有的请求方式都允许被调用的,比如说提交表单的HTTP请求处理方法,可能只允许使用POST 方式提交的才能够被调用,而实用GET方式提交的请求是不被允许的.为 ...

  5. 图解HTTP-HTTP

    文章目录 HTTP HTTP是不保存状态的协议(对请求和响应不做持久化处理) 请求URI定位资源 HTTP中的方法 1.GET(获取资源) 2.POST( 传输实体主体) 3.PUT(传输文件) 4. ...

  6. 计算机网络,看这篇就够了

    因特网 因特网是世界范围的计算机网络,即它互联了全球数十亿计算设备(叫主机或者端系统)的网络.下图可作为因特网全貌结构. 端系统通过通信链路与分组交换机连接到一起.当端系统要向另一台端系统发数据时,会 ...

  7. 如何进行接口测试(一篇学会)

    1.接口概念: 在计算机中,接口是计算机系统中两个独立的部件进行信息交换的共享边界.这种交换可以发生在计算机软.硬件,外部设备或进行操作的人之间,也可以是它们的结合. 2.接口测试的作用: 主要用于检 ...

  8. HTTP的几种请求方法

    HTTP的几种请求方法 方法 作用 支持版本 GET 获取资源 1.0.1.1 POST 传输实体主体 1.0.1.1 HEAD 获取报文首部 1.0.1.1 PUT 传输文件 1.0.1.1 DEL ...

  9. HTTP/HTTPS协议

    文章目录 背景概念 应用层 "协议" 序列化与反序列化 场景:网络版本的计算器 http协议 认识URL urlencode和urldecode HTTP协议的格式 编写代码查看h ...

最新文章

  1. AI给老照片上色,真的准吗?技术圈和历史圈吵了1000帖
  2. Eclipse Android编程快捷键
  3. Python 技术篇-基于随机数的uuid码的生成
  4. 如何多次读取request请求里的数据
  5. android如何让service不被杀死-提高进程优先级
  6. [pytorch、学习] - 9.2 微调
  7. Mysql8秒级加字段_Mysql8.0秒级加字段
  8. js html form,JavaScript 表单
  9. html参考文献_毕业设计参考文献格式(要求与范例)
  10. linux文件系统命令
  11. curl如何发送json数据?如何发送form数据?python的restfull又该如何获取这些数据?...
  12. python如何逐行读取文件_python怎么逐行读写txt文件
  13. 【密码学基础】06 高级加密标准AES
  14. TCP通讯中发送文件
  15. Windows Server2008 R2搭建域环境(步骤最详细)
  16. mapreduce面试问题_MapReduce问题与解答第2部分
  17. 数字逻辑综合工具-DC-04 ——怎样增加时序约束(Timing Constraints)
  18. 关于CSS选择器的权重计算
  19. PCL点云(平面点云)分割:Plane Model Segmentation
  20. 一键万能搜索框,这个chrome插件有点好用!

热门文章

  1. trait功能 php,PHP之Trait功能与用法实例分析
  2. 主键可以增加查询速度吗_米脂起重信号工含金量高吗 可不可以联网查询在哪里查c...
  3. 电脑常用音频剪辑软件_如何使用音频剪辑软件,快速剪辑任意格式音频!
  4. 杰奇程序 php文件设置,JIEQI CMS使用技巧
  5. 创建QT项目时只有.pro文件,源文件和头文件
  6. Access中字段类型及修改字段类型的SQL语句
  7. 阳台花园不只美丽-东方美琪·安琪:身心健康谋定心灵升华
  8. 一次搞懂建模语言UML
  9. eclipse的任务列表
  10. 最大并发连接数和最大会话数的区别