CSAPP Chapter 10 System-Level I/O 学习笔记(不定期更新)

CSAPP Chapter 10 System-Level I/O 学习笔记(不定期更新)

学习进度

  • 10.1 Unix I/O
  • 10.2 Files

10.1 Unix I/O

学习契机

在学习CSAPP第11章的socket套接字接口的时候,在介绍相关的方法时,提到了大量的 file descriptor 的参数,发现这个概念有点陌生了,就来复习巩固一下。这么说来我对于各种语言的文件读写一直都有一种望而却步能用就行的感觉,没有好好的学习使用过,从Unix I/O开始也可以打下一个良好的基础。

什么是I/O

I/O就是Input和Output,是对于 main memory 主存与 external devices 外部设备(e.g., 硬盘,终端以及网络)之间数据的输入与输出:

  • Input:将数据从从I/O设备中拷贝到主存中
  • Output:将数据从内存中拷贝到外部设备上

Unix中的I/O

关于Unix中I/O的具体实现,首先我们要了解的两个很重要的结论:

  1. 在Unix中,所有的I/O设备都是以 文件 的形式存储和操作
  2. 那么所有这些I/O操作都是通过读写这些文件来实现的

其中,Wikipedia对于I/O 设备的定义如下: “I/O devices are the pieces of hardware used by a human (or other system) to communicate with a computer … Devices for communication between computers, such as modems and network cards, typically perform both input and output operations.”

了解到了这两点之后, 所有 的I/O操作就可以规范地定义为对于 文件 的几个规范性操作,也就是Interface接口:

Opening files, 打开文件
  • 触发:当一个应用想要访问操作一个I/O设备(想要输入或者输出)的时候,就会要求kernel去打开对应的代表I/O设备的文件
  • 结果:Kernel内核会返回一个很小的正整数,我们叫做 descriptor 描述符,用来在之后对于该I/O设备文件的所有操作中,唯一标识该文件
  • Kernel内核会持续跟踪该打开文件的所有的信息;而应用只会跟踪返回的 descriptor 描述符
  • 每一个运行的进程会由Linux shell通过打开三个文件开启(个人认为就是启动一个进程需要用到三种I/O设备,因此开启了这三个文件,并返回了三个描述符):
    1. standard input (descriptor 0) 标准输入
    2. standard output (descriptor 1) 标准输出
    3. standard error (descriptor 2) 标准错误
Changing the current file position 改变当前文件(内容)位置
  • File position文件位置表示文件中下一个将要被读写的字符的位置
  • Kernel会维护每一个打开的文件的file position k
  • k的初始值为0,每次有字符的读写,file position都会自增
  • 应用也可以通过 seek 操作来显示地修改file position
Reading and writing files 读写文件
  • Read 读文件:从一个文件中读取n bytes的数据,从该文件当前的file position k开始读,并且递增n
    • 如果读文件超过文件的size m,则会触发 end-of-file (EOF), 值得注意的是,这是由应用自动检测到的,而不是真的有一个字符叫做EOF符
  • Write 写文件,同样也会递增file position k文件位置
Closing files 关闭文件
  • 触发:当应用结束访问一个文件的时候,就会要求kernel去 close 关闭这个文件
  • 结果:kernel会释放所有的所有该文件创建的数据结构;并且将该文件的 descriptor 描述符归还到可用的描述符池中去
  • 当一个进程结束时,kernel会关闭所有打开的文件并且释放他们的内存资源,比如之前提到的标准输入/输出/错误文件,都会被关闭

10.2 Files 文件

学习契机

跟随10.1顺便看看

文件分类

Linux中对于不同的文件都有其所对应的分类

regular file 常规文件
一个普通文件中可以包含任意数据,根据内容存储形式的不同,我们还可以再细化为:
  1. text files, 文本文件,即只包含ASCII或者Unicode字符的文件

    • 其中文本文件包含一串 text lines 文件行,每一行都由 newline 符号 '\n' 结尾(Linux, Mac OSX)

    • 再Ms Windows以及Internet协议例如HTTP中,则是使用 '\r\n' (0xd 0xa)表示的

    • 因此当我们在Linux以及Mac OSX环境下阅读由MS Windows编辑的文本文件时,每行后面都会出现 ‘^M’,可以使用一下命令来进行清理

      linux> perl -pi -e "s/\r\n/\n/g" foo.txt
      
  2. binary files,二进制文件,

directory 目录
  • 目录时一个包含一组 links 链接的文件,每一个链接都对应一个文件(常规文件或者目录)

  • 每一个目录文件至少包含两个默认链接

    • . (dot), 该链接指向该目录文件本身
    • .. (dot-dot),该链接指向 parent directory
    • mkdir 创建目录文件, ls 查看内容, rmdir 删除目录
socket 套接字
  • 套接字文件用来与其他进程进行网络通信(详见11.4)

文件目录结构

Linux内核通过唯一一个目录结构来管理所有的文件,该结构是由 root directory 根目录开始的一个树状结构,用 / 来表示,因此我们在一个文件路径中开头看到 / 要知道,这是一个目录文件,和后面使用到的 / 用作分隔符的概念时不一样的

Figure 1: Linux目录结构

Figure 1: Linux目录结构

每一个进程都有一个 current working directory 用来表示其在这个目录结构中的位置,通过 cd 命令可以改变shell的 current working directory

那么对应Linux目录结构,有两种形式来表达一个文件的位置(Location):

  1. Absolute pathname, 绝对路径,表示从根目录(/)开始的路径(之后的/表示路径的分割),例如上图中的hello.c文件的绝对路径就是/home/droh/hello.c
  2. Relative pathname,相对路径,表示从一个文件名(./..也是文件名)开始,表示一个文件对于当前工作路径的相对路径,例如在上图中,我们当前的工作路径为 /home/droh,那么文件 hello.c的相对路径就是./hello.c

Reference

Randal E. Bryant, David R. O’Hallaron - Computer Systems. A Programmer’s Perspective [3rd ed.] (2016, Pearson)

CSAPP 读书笔记:系统级 I/O

GNU: File Position

Licensed under CC BY-NC-SA 4.0
Last updated on Sep 27, 2022 11:24 CST
comments powered by Disqus
Cogito, ergo sum
Built with Hugo
Theme Stack designed by Jimmy