深入理解计算机系统(第3版) 第十章 系统级I/O

1.输入和输出(I/O)

输入和输出(I/O)是在主存和外部设备(例如磁盘驱动器、终端和网络)之间复制数据的过程。输入操作是从I/O设备复制数据到主存,而输出操作是从主存复制数据到I/O设备。

所以语言运行时系统都提供执行I/O的较高级别的工具。例如,ANSI C提供标准I/O库,包含像printf和scanf这样执行带缓冲区的I/O函数。C++语言用它的重载操作符<<(输入)和>>(输出)提供了类似的功能。在linux系统中,是通过使用由内核通过的系统级unix I/O函数来实现这些较高级别的I/O函数的。大多数时候,高级别I/O函数工作良好,没有必要直接使用unix I/O。

 

2.文件

每个Linux文件都有一个类型(type)来表明它在系统中的角色。

-->普通文件(regular file):包含任何数据。应用程序常常要区分文本文件(text file)和二进制文件(binary file),文本文件是只含有ASCII或Unicode字符的普通文件;二进制文件是所有其他的文件。对内核而言,文本文件和二进制文件没有区别。linux文本文件包含了一个文本行(text line)序列,其中每一行都是一个字符序列,以一个新行符('\n')结束。新行符与ASCII的转行符(LF)是一样的,其数字值为0x0a。

-->目录(directory):是包含一组链接(link)的文件。其中每个链接都将一个文件名(filename)映射到一个文件,这个文件可能是另一个目录。每个目录至少包含两个条目:‘.'是到该目录自身的链接,以及'..'是到目录结构层次中父目录(parent directory)的链接。你可以用mkdir命令创建一个目录,用ls查看其内容,用rmdir删除该目录。

-->套接字(socket):是用来与另一个进程进行跨网络通信的文件。

其他文件类型包含命名通道(named pipe)、符号链接(symbolic link)以及字符和块设备(charactor and block device)。

Linux内核将所有文件都组织成一个目录层次结构(directory hierarchy),由名为/(斜线)的根目录确定。系统中的每个文件都是根目录的直接或间接的后代,如下图,

目录层次结构中的位置用路径名(filename)来指定。路径名是一个字符串,包括一个可选斜杠,其后紧随一系列的文件名,文件名之间用斜杠分隔。路径名有两种形式:

-->绝对路径名(absolute filename):以一个斜杠开始,表示从根节点开始的路径。如上图,hello.c的绝对路径名为/home/droh/hello.c。

-->相对路径名(relative filename):以文件名开始,表示从当前工作目录开始的路径。如上图,如果/home/droh是当前的工作目录,那么hello.c的相对路径名为./hello.c;如果/home/bryant是当前的工作目录,那么相对路径名就是../home/droh/hello.c。

 

3.打开和关闭文件

进程是通过调用open函数来打开一个已存在的文件或者创建一个新文件。

 

4.读和写文件

应用程序是通过分别调用read和write函数来执行输入和输出。

 

5.用RIO包健壮地读写

RIO提供了两类不同的函数。

-->无缓冲的输入输出函数:这些函数直接在内存和文件之间传送数据,没有应用级缓冲。它们对将二进制数据读写到网络和从网络读写二进制数据尤其有用。

-->带缓冲的输入函数:这些函数允许高效地从文件中读取文本行和二进制数据,这些文件的内容缓存在应用级缓冲区内,类似于为printf这样的标准I/O函数提供的缓冲区。与带缓冲的I/O例程不同,带缓冲的RIO输入函数是线程安全的,它在同一个描述符上可以被交错的调用。例如,你可以从一个描述符中读取一些文本行,然后读取一些二进制数据,接着再多读取一些文本行。

 

6.读取文件元数据

应用进程能够通过调用stat和fstat函数,检索到关于文件的信息(有时也称为文件的元数据(metadata))。

 

7.读取目录内容

应用程序可以用readdir序列函数来读取目录的内容。

 

8.共享文件

可以用许多不同的方式来共享Linux文件。除非你很清楚内核是如何表示打开的文件,否则文件共享的概念相当难懂。内核用三个相关的数据结构来表示打开的文件。

-->描述符表(descriptor table):每个进程都有它独立的描述符表,它的表项是由进程打开的文件描述符来索引的。每个打开的描述符表项指向文件表中的一个表项。

-->文件表(file table):打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。每个文件表的表项组成包括当前的位置、引用计数,以及一个指向v-node表中对应表项的指针。关闭一个描述符会减少相应的文件表表项中的引用计数。内核不会删除这个文件表表项,直到它的引用计数为零。

-->v-node表(v-node table):同文件表一样,所有的进程共享这张v-node表。每个表项包含stat结构中的大多数信息,包括st_mode和st_size成员。

 

9.I/O重定向

Linux shell提供了I/O重定向操作符,允许用户将磁盘文件和标准输入输出联系起来。

例如,键入:linux > ls > foo.txt

使得shell加载和执行ls程序,将标准输出重定向到磁盘文件foo.txt。

实现方式,通过使用dup2函数。

 

10.标准I/O

C语言定义了一组高级输入输出函数,称为标准I/O库,为程序员提供了Unix I/O的较高级别的替代。这个库(libc)提供了打开和关闭文件的函数(fopen和fclose)、读和写字节的函数(fread和fwrite)、读和写字符串的函数(fgets和fputs),以及复杂的格式化的I/O函数(scanf和printf)。

标准I/O库将一个打开的文件模型化为一个流,对于程序员而言,一个流就是一个指向FILE类型的结构的指针。每个ANSI C程序开始时都有三个打开的流(stdin、stdout、stderr,分别对应于标准输入、标准输出和标准错误)。

 

第十章小结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值