read系统调用深度剖析

本文转自:http://blog.csdn.net/unbutun/article/details/6101354#ibm-pcon

Read 系统调用在用户空间中的处理过程

Linux 系统调用(SCI,system call interface)的实现机制实际上是一个多路汇聚以及分解的过程,该汇聚点就是 0x80 中断这个入口点(X86 系统结构)。也就是说,所有系统调用都从用户空间中汇聚到 0x80 中断点,同时保存具体的系统调用号。当 0x80 中断处理程序运行时,将根据系统调用号对不同的系统调用分别处理(调用不同的内核函数处理)。系统调用的更多内容,请参见参考资料。

Read 系统调用也不例外,当调用发生时,库函数在保存 read 系统调用号以及参数后,陷入 0x80 中断。这时库函数工作结束。Read 系统调用在用户空间中的处理也就完成了。


Read 系统调用在核心空间中的处理过程

0x80 中断处理程序接管执行后,先检察其系统调用号,然后根据系统调用号查找系统调用表,并从系统调用表中得到处理 read 系统调用的内核函数 sys_read ,最后传递参数并运行 sys_read 函数。至此,内核真正开始处理 read 系统调用(sys_read 是 read 系统调用的内核入口)。

在讲解 read 系统调用在核心空间中的处理部分中,首先介绍了内核处理磁盘请求的层次模型,然后再按该层次模型从上到下的顺序依次介绍磁盘读请求在各层的处理过程。

Read 系统调用在核心空间中处理的层次模型

图1显示了 read 系统调用在核心空间中所要经历的层次模型。从图中看出:对于磁盘的一次读请求,首先经过虚拟文件系统层(vfs layer),其次是具体的文件系统层(例如 ext2),接下来是 cache 层(page cache 层)、通用块层(generic block layer)、IO 调度层(I/O scheduler layer)、块设备驱动层(block device driver layer),最后是物理块设备层(block device layer)


图1 read 系统调用在核心空间中的处理层次
 

  • 虚拟文件系统层的作用:屏蔽下层具体文件系统操作的差异,为上层的操作提供一个统一的接口。正是因为有了这个层次,所以可以把设备抽象成文件,使得操作设备就像操作文件一样简单。
  • 在具体的文件系统层中,不同的文件系统(例如 ext2 和 NTFS)具体的操作过程也是不同的。每种文件系统定义了自己的操作集合。关于文件系统的更多内容,请参见参考资料。
  • 引入 cache 层的目的是为了提高 linux 操作系统对磁盘访问的性能。 Cache 层在内存中缓存了磁盘上的部分数据。当数据的请求到达时,如果在 cache 中存在该数据且是最新的,则直接将数据传递给用户程序,免除了对底层磁盘的操作,提高了性能。
  • 通用块层的主要工作是:接收上层发出的磁盘请求,并最终发出 IO 请求。该层隐藏了底层硬件块设备的特性,为块设备提供了一个通用的抽象视图。
  • IO 调度层的功能:接收通用块层发出的 IO 请求,缓存请求并试图合并相邻的请求(如果这两个请求的数据在磁盘上是相邻的)。并根据设置好的调度算法,回调驱动层提供的请求处理函数,以处理具体的 IO 请求。
  • 驱动层中的驱动程序对应具体的物理块设备。它从上层中取出 IO 请求,并根据该 IO 请求中指定的信息,通过向具体块设备的设备控制器发送命令的方式,来操纵设备传输数据。
  • 设备层中都是具体的物理设备。定义了操作具体设备的规范。

相关的内核数据结构:

  • Dentry : 联系了文件名和文件的 i 节点
  • inode : 文件 i 节点,保存文件标识、权限和内容等信息
  • file : 保存文件的相关信息和各种操作文件的函数指针集合
  • file_operations :操作文件的函数接口集合
  • address_space :描述文件的 page cache 结构以及相关信息,并包含有操作 page cache 的函数指针集合
  • address_space_operations :操作 page cache 的函数接口集合
  • bio : IO 请求的描述

数据结构之间的关系:

图2示意性地展示了上述各个数据结构(除了 bio)之间的关系。可以看出:由 dentry 对象可以找到 inode 对象,从 inode 对象中可以取出 address_space 对象,再由 address_space 对象找到 address_space_operations 对象。

File 对象可以根据当前进程描述符中提供的信息取得,进而可以找到 dentry 对象、 address_space 对象和 file_operations 对象。


图2 数据结构关系图:
 

前提条件:

对于具体的一次 read 调用,内核中可能遇到的处理情况很多。这里举例其中的一种情况:

  • 要读取的文件已经存在
  • 文件经过 page cache
  • 要读的是普通文件
  • 磁盘上文件系统为 ext2 文件系统,有关 ext2 文件系统的相关内容,参见参考资料

准备:

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TCP read函数是一个系统调用,用于从TCP连接的输入缓冲区中读取数据。它的功能是从连接的另一端发送的数据流中读取指定数量的字节,并将其存储在指定的缓冲区中。 当调用read函数时,首先会检查输入缓冲区中是否有足够的数据可供读取。如果没有足够的数据,函数会阻塞并等待数据到达,直到有足够的数据可供读取。 一旦有足够的数据可供读取,read函数会从输入缓冲区复制指定数量的字节到指定的缓冲区中。在复制完成后,它将返回实际复制的字节数。 如果在读取数据时出现错误,read函数会返回一个负值,表示出错的类型。一些可能的错误类型包括连接中断、连接重置、超时等。 在使用read函数时,需要注意以下几点: 1. 指定的缓冲区必须有足够的空间来存储读取的数据,否则可能会发生数据截断或缓冲区溢出的情况。 2. 在多线程或多进程环境下使用read函数时要进行同步操作,以避免竞争条件和数据一致性问题。 3. 在使用非阻塞模式的套接字时,read函数可能返回0,表示读取到达EOF(文件结束)。 总结起来,TCP read函数是一个重要的系统调用,用于从TCP连接中读取数据。它的功能是将指定数量的字节从输入缓冲区复制到指定的缓冲区中,并返回实际复制的字节数。在使用read函数时需要注意数据截断、缓冲区溢出、同步操作和非阻塞模式等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值