“人生苦短,不如养狗
”
一、从I/O开始
在学习和使用计算机的过程中基本绕不开这样一个概念—— I/O ,也即输入/输出,指的是一切操作、程序或设备与计算机之间发生的数据传输过程。
对于计算机而言, I/O操作 和 计算处理 是贯穿它一生的两大主要任务,其中大多数时间都是在执行I/O操作。这里所说的I/O操作实际上分为硬件和软件两个部分,分别是I/O设备和I/O子系统。
I/O设备
时至今日,I/O设备的种类愈加繁多,从功能上(或者说工作方式上)可以对这些设备进行如下划分:
存储设备
: 又叫块设备,这类设备将信息存储在固定大小的块当中,每个块都有自己的地址,且每块都能独立于其他块进行读写。较为常见的存储设备有磁盘、磁带。传输设备
: 又叫网络通信设备,这类设备主要用于与远程设备进行通信,常见的传输设备有网卡、Modem。人机交互设备
: 又叫字符设备,这类设备在I/O传输过程以字符为单位进行信息的传输。较为常见的字符设备有屏幕、键盘、鼠标,由于字符设备是直面用户的设备,且通过这些设备用户能够和计算机产生交互,所以这类设备又叫人机交互设备。特殊设备
: 除了上述三种设备以外的可以进行I/O传输的设备都可以归类为特殊设备。
可以看到I/O设备种类繁杂,且彼此之间存在很大差异。为了对上层应用程序屏蔽底层设备的差异和细节,同时为了进行硬件和软件接口的标准化,操作系统内核设计成使用 设备驱动程序模块 的结构。设备驱动程序为I/O子系统提供了统一的设备访问接口,就像系统调用为应用程序与操作系统之间提供了统一的标准接口。但同时需要注意一点,I/O设备和设备驱动程序(计算机)的通信实际上是通过 硬件接口(端口) 来完成的,这一过程需要软硬件共同合作才能完成。
I/O接口(I/O子系统)
再华丽的硬件如果没有对应匹配的软件提供控制管理的能力,硬件本应该提供的服务将最终无法得到使用。就如上文所说的,对与计算机相连设备(I/O设备)的控制是操作系统的主要任务之一,而这些用于控制设备的多种方法的集合就构成了 I/O子系统 。
正如上面所说的,随着I/O设备的不断发展,I/O设备的种类愈加繁多,如果没有标准的、抽象的I/O操作接口,就会导致新类型的I/O很难接入操作系统。为了屏蔽底层硬件设备的差异和细节,操作系统使用设备驱动程序来抽象和统一了设备的访问接口,具体的实现由硬件设备的厂商自行实现。(可以看到,面向抽象编程的思想很早就兴起了)
聊完了I/O的一些基本概念,下面我们来看一看在日常开发过程中经常会遇到的两个概念: 文件I/O 和 网络I/O 。
二、文件I/O
我们即将讨论的 文件I/O 这一概念更多偏向于软件层面,也即操作系统层面。在操作系统当中,为了方便用户或者开发人员对于数据信息(由外设提供)的使用,操作系统对存储设备的各种属性加以抽象,从而定义了逻辑存储单元(文件),再将文件映射到物理设备上。需要注意的是,文件的概念不仅适用于存储设备,还适用于其他I/O设备,两者的区别在于文件类型和操作系统对于两种不同类型文件的操作。这也验证了Linux当中的一句话:“一切皆文件”。(这里再一次出现了面向对象的设计理念)这里我们只单纯讨论存储设备相关的文件I/O概念。
从上图可以看到,如果一个应用程序想要发起一个文件I/O请求需要通过操作系统当中的文件系统来完成对应的I/O操作。上面我们也提到了,操作系统提供给用户可以操作的逻辑存储单元为文件(在UNIX环境中使用了 文件描述符 这样一个概念),这个可以操作的文件对象包含了实际被操纵对象的基本属性,操作系统将其抽象为文件属性,比如名称、标识符、类型、位置、大小、保护、用户标识以及时间等信息。针对文件这样一个抽象数据类型,文件系统提供了创建、写、度、定位、删除和截短等系统调用。
如果我们将文件I/O的概念进一步限制到Linux环境中,又可以将其成为低级磁盘I/O,任何兼容POSIX标准的操作系统都能够支持文件I/O。同时文件I/O能够访问存储设备当中不同类型的文件,但是访问文件时并不会通过缓冲区,而是会直接通过系统调用进行对应资源的访问。
三、网络I/O
我们日常讨论的网络通信本质上就是网络I/O,通过网络I/O,我们可以和远程设备进行通信(数据交换)。由于网络I/O和正常的磁盘I/O在性能和访问方式上有较大的差异,所以针对磁盘I/O的读写方法也就无法适用于网络I/O身上,大部分操作系统针对网络I/O抽象除了一套特殊的接口—— 网络Socket接口 ,用于对网络I/O进行操作。当然,上面也说了,在Linux当中“一切皆文件”,为了统一概念,Socket在Linux当中也是通过文件描述符来进行描述的,只不过这个文件描述符描述的不是本地文件,而是远程设备对应的文件。
由于网络通信存在不可预知的问题,所以诞生了诸多I/O模型,这些I/O模型本质上是一种客户端(或者说是服务消费者)对网络I/O请求的处理方式。由于网络上这类资料还是非常多的,这里就不铺开描述了。
四、总结
从大的概念来看,文件I/O和网络I/O本质上都是对资源的访问,只不过一个是本地设备,一个是远程设备。但是从访问方式和性能上来看,文件I/O和网络I/O无论是在I/O接口和系统调用上都有很大差别。