跳转至

0x05.I/O

*NIX/Linux追求高层次抽象上的统一,其设计哲学之一便是万物皆文件

一、“万物皆文件”

NIX/Linux设计的哲学之一——万物皆文件,在Linux系统的视角下,无论是文件、设备、管道,还是目录、进程,甚至是磁盘、套接字等等,一切都可以被抽象为文件,一切都可以使用访问文件的方式进行操作*

通过这样一种哲学,Linux予开发者以高层次抽象的统一性,提供了操作的一致性

  • 所有的读取操作都可以通过对文件进行 read 系统调用完成
  • 所有的更改操作都可以通过对文件进行 write 系统调用完成
  • 所有的配置操作都可以通过对文件进行 ioctl 系统调用完成

对于开发者而言,将一切的操作都统一于一个高层次抽象的应用接口,无疑是十分美妙的一件事情——我们不需要去理解实现的细节,只需要对"文件"完成简单的读写操作

例如,在较老版本的Linux中,可以使用cat /dev/urandom > /dev/dsp命令令扬声器产生随机噪声

image.png

二、进程文件系统

进程文件系统(process file system, 简写为procfs)用以描述一个进程,其中包括该进程所打开的文件描述符、堆栈内存布局、环境变量等等

进程文件系统本身是一个伪文件系统,通常被挂载到/proc目录下,并不真正占用储存空间,而是占用一定的内存

当一个进程被建立起来时,其进程文件系统便会被挂载到/proc/[PID]下,我们可以在该目录下查看其相关信息

三、文件描述符

进程通过文件描述符file descriptor)来完成对文件的访问,其在形式上是一个非负整数,本质上是对文件的索引值,进程所有执行 I/O 操作的系统调用都会通过文件描述符

每个进程都独立有着一个文件描述符表,存放着该进程所打开的文件索引,每当进程成功打开一个现有文件/创建一个新文件时(通过系统调用open进行操作),内核会向进程返回一个文件描述符

在kernel中有着一个文件表,由所有的进程共享

stdin、stdout、stderr

每个*NIX进程都应当有着三个标准的POSIX文件描述符,对应着三个标准文件流:

  • stdin:标准输入 - 0
  • stdout:标准输出 - 1
  • stderr:标准错误 - 2

此后打开的文件描述符应当从标号3起始

四、系统调用:ioctl

在*NIX中一切都可以被视为文件,因而一切都可以以访问文件的方式进行操作,为了方便,Linux定义了系统调用ioctl供进程与设备之间进行通信

系统调用ioctl是一个专用于设备输入输出操作的一个系统调用,其调用方式如下:

int ioctl(int fd, unsigned long request, ...)
  • fd:设备的文件描述符
  • request:请求码
  • 其他参数

对于一个提供了ioctl通信方式的设备而言,我们可以通过其文件描述符、使用不同的请求码及其他请求参数通过ioctl系统调用完成不同的对设备的I/O操作

例如CD-ROM驱动程序弹出光驱的这一操作就对应着对“光驱设备”这一文件通过ioctl传递特定的请求码与请求参数完成