【小镇的技术之路】Linux中的文件描述符

Scapy学习日志的第二篇过两天再发,因为学习Scapy要开虚拟机,只能回家用性能较好的电脑才能学习。在单位就学习学习Linux的基础知识吧。
该篇文章的大部分内容是网上的资料。部分较难的我自己翻译了下。卧槽,其实有些我也看不懂......反正后续再把不会的知识补上吧。

1、概述
首先,大家需要理解一个概念,那就是在Linux系统中,所有的一切都可以看成是文件。
文件又可分为:普通文件、目录文件、链接文件和设备文件。
Linux系统内核为了高效管理已经被打开的文件,就给每个文件建立了一个索引,索引的值是一个非负的整数,所有执行I/O操作的系统调用都是通过文件描述符来进行的。在程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。
2、文件描述符合打开文件之间的关系
每一个文件描述符一定会与一个打开的文件相对应,但是,不同的文件描述符也可以指向同一个文件。相同的文件可以被不同的进程打开也可以在同一个进程中被多次打开。文件描述符的表示依附于进程的,Linux系统为每一个进程维护了一个文件描述符的表,该表的值都是从0开始的,所以在不同的进程中,我们会看到相同的文件描述符。所以这完全是多对多的情况,具体的情况要去具体的分析。
内核有关文件描述符维护了3个数据结构。
    1. 进程级的文件描述符表
    2. 系统级的打开文件描述符表
    3. 文件系统的i-node表

进程级的描述符表的每一条目记录了单个文件描述符的相关信息。
    1. 控制文件描述符操作的一组标志。(目前,此类标志仅定义了一个,即close-on-exec标志)
    2. 对打开文件句柄的引用

 内核对所有打开的文件的文件维护有一个系统级的描述符表格(open file description table)。有时,也称之为打开文件表(open file table),并将表格中各条目称为打开文件句柄(open file handle)。句柄大家都知道吧,小镇就是想象成文件的把柄,通过这个把柄就能获取文件的信息了对吧。一个打开文件句柄存储了与一个打开文件相关的全部信息,如下所示:
 1. 当前文件偏移量(调用read()和write()时更新,或使用lseek()直接修改)
 2. 打开文件时所使用的状态标识(即,open()的flags参数)
 3. 文件访问模式(如调用open()时所设置的只读模式、只写模式或读写模式)
 4. 与信号驱动相关的设置
 5. 对该文件i-node对象的引用
 6. 文件类型(例如:常规文件、套接字或FIFO)和访问权限
 7. 一个指针,指向该文件所持有的锁列表
 8. 文件的各种属性,包括文件大小以及与不同类型操作相关的时间戳
 【改部分摘自于我查找的资料,写的通俗易懂,我就不翻译了。】
 【其实小镇就看懂了2、3、5、6、7,不懂的我会在后续的文章中补充相关的知识。】

 下图展示了文件描述符、打开的文件句柄以及i-node之间的关系,图中,两个进程拥有诸多打开的文件描述符。
 【i-node是个很好理解的概念,小镇在这里给大家解释下,大家都知道文件是存在硬盘里面的,而硬盘里面的最小的存储单位叫做扇区,操作系统为了提高IO效率,会一次性的连续读取多个扇区,也就是一次性低读取一个“块”,没错!!这个多个扇区组合起来的块就是文件存取的最小单位啦~而inode存取了文件的元信息,其中有很多信息,但是最重要的就是这个文件存储在哪些块上,所以inode就像是文件的身份证一样!】


请看下图!!



在进程A中,文件描述符1和30都指向了同一个打开的文件句柄(标号23)。这可能是通过调用dup()、dup2()、fcntl()或者对同一个文件多次调用了open()函数而形成的。
【小镇来翻译一下,so easy,就是一个进程开了好多次这个文件啊啊啊啊!这些函数都有着打开该文件的功能】
进程A的文件描述符2和进程B的文件描述符2都指向了同一个打开的文件句柄(标号73)。这种情形可能是在调用fork()后出现的(即,进程A、B是父子进程关系),或者当某进程通过UNIX域套接字将一个打开的文件描述符传递给另一个进程时,也会发生。
【这就更简单了。。两个进程都打开了这个文件呗~,fork()函数是用来复制进程的!但是小镇要提醒下,这边的进程内部描述符都是fd2,这很大可能是fork的结果,但是也有可能两个进程都打开了改文件,又正好分配到了相同的内部文件描述符。所以fd2相同不是必然事件,希望大家不要搞混,免得概念不清】


3、总结
1. 由于进程级文件描述符表的存在,不同的进程中会出现相同的文件描述符,它们可能指向同一个文件,也可能指向不同的文件
【这个大家都懂吧。。。刚刚在上面已经解释过啦】
2. 两个不同的文件描述符,若指向同一个打开文件句柄,将共享同一文件偏移量。因此,如果通过其中一个文件描述符来修改文件偏移量(由调用read()、write()或lseek()所致),那么从另一个描述符中也会观察到变化,无论这两个文件描述符是否属于不同进程,还是同一个进程,情况都是如此。
【这个嘛,就跟c语言中传递的参数是一个值的指针,然后当你通过指针改变了改值的时候,函数外引用的该值发生变化是一个道理】
3.要获取和修改打开的文件标志(例如:O_APPEND、O_NONBLOCK和O_ASYNC),可执行fcntl()的F_GETFL和F_SETFL操作,其对作用域的约束与上一条颇为类似。
【反正就是修改文件的标志呗,按照规则来就行啦】


4. 文件描述符标志(即,close-on-exec)为进程和文件描述符所私有。对这一标志的修改将不会影响同一进程或不同进程中的其他文件描述符
【改标志是文件描述符的私有属性,互不干扰~】
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值