20145233 《信息安全系统设计基础》第九周学习总结

20145233 《信息安全系统设计基础》第九周学习总结

教材学习内容总结

第一节 Unix I/O

这一节涉及到操作系统的基本抽象之一——文件。也就是说,所有的I/O设备都被模型化为文件,而所有的输入输出都被当做对相应文件的读/写。相关的执行动作如下:

打开文件

  • 应用程序向内核发出请求→要求内核打开相应的文件→内核返回文件描述符

  • 文件描述符:一个小的非负整数,用来在后续对此文件的所有操作中标识这个文件。有三个已经被指定了的如下:

标准输入——0(STDIN_FILENO)
标准输出——1(STDOUT_FILENO)
标准错误——2(STDERR_FILENO)

括号中是常量表示形式,使用时需要加头文件<unistd.h>

改变当前的文件位置

  • 通常,读,写操作都从当前文件偏移量处开始(也就是文件位置),并使偏移量增加所读写的字节数,可以理解为光标所在的位置。

  • 当打开一个文件的最初时候文件的偏移量为0.

  • 通过seek操作,可以显示的设置文件的当前位置为k。

读写文件

(1)读

读操作就是从文件拷贝n>0个字节到存储器,并且改变文件当前位置。(如果当前位置是k,则改变为k+n)

EOF的来源:

  • 这里有一个理解上的误区:文件结尾处没有明确的EOF信号,是当文件当前位置的数值超过了文件大小时,会处罚一个称为end-of-file的条件,能够被应用程序检测到,这就是所谓的EOF信号。

(2)写

  • 写操作是从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置,然后更新当前文件位置。

关闭文件

  • 应用通知内核关闭文件→内核释放文件打开时的数据结构→恢复描述符→释放存储器资源。

第二节 打开和关闭文件

  • 打开一个已存在的文件或者创建一个新文件:int open(char *filename,int flags,mode_t mode) (若成功则返回新文件描述符,若出错为-1)
  • open函数将filename转换为一个文件描述符,并且返回描述符数字。
  • flags参数指明了进程如何访问文件。
  • mode参数指定了新文件的访问权限位。
  • 关闭一个打开的文件:int close(int fd)(若成功则为0,若出错则为-1)
    关闭一个已关闭的描述符会出错

第三节 读和写文件

  • read函数从描述符为fd的当前文件位置拷贝最多n个字节到存储器位置buf,返回值-1表示一个错误。而返回值0表示EOF。否则,返回值表示的是实际传送的字节数量。
  • write函数从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置。
  • 在某些情况下,read和write传送的字节比应用程序要求的要少原因如下:
1、读时遇到EOF。假设我们猪呢比读一个文件,该文件从当前文件位置开始只含有20多个字节,而我们以50个字节的片进行读取。这样一来,下一个read返回的不足值为20,此后的read将通过返回不足值0来发出EOF信号。
2、从终端读文本行。如果打开文件是与终端相关联的(如键盘和显示器),那么每个read函数将以此传送一个文本行,返回的不足值等于文本行的大小。
3、读和写网络套接字。如果打开的文件对应于网络套接字,那么内部缓冲约束和较长的网络延迟会引起read和write返回不足值。对Unix管道调用read和write时,也有可能出现不足值,这种进程间的通信机制不在我们讨论的范围之内。

不足值

  • 读时遇到EOF:文件末尾剩余的字节数不足读取文件的字节片大小。
  • 从终端读文本行:若打开文件与终端相关联,则每个read函数将一次传送一个问本行。返回的不足值等于文本行的大小。
  • 读和写网络套接字(socket):若打开的文件对应于网络套接字,那么内部缓冲约束和较长的网络延迟会引起read和write返回不足值。

第四节 用RIO包健壮地读写

  • RIO包会自动处理不足值。
  • RIO提供了两类不同的函数:
    • 无缓冲的输入输出函数。这些函数直接在存储器和文件之间传送数据,没有应用级缓冲,对将二进制数据读写到网络和从网络读写二进制数据尤其有用。
    • 带缓冲的输入函数。这些函数允许高效地从文件中读取文本行和二进制数据(函数从内部缓冲区中拷贝一个文本行,当缓冲区变空的时候,会自动地调用read重新填满缓冲区),这些文件的内容缓存在应用级缓冲区内,类似于像printf这样的标准I/O函数提供的缓冲区。带缓冲的RIO输入函数是线程安全的,它在同一个描述符上可以被交错地调用。

第五节 读取文件数据

  • 元数据即文件信息,需要用到的函数是stat和fstat
  • stat需要输入文件名,而fstat需要输入的是文件描述符。
  • 文件类型:
普通文件:二进制或文本数据,宏指令:S_ISREG()
目录文件:包含其他文件的信息,宏指令:S_ISDIR()
套接字:通过网络和其他进程通信的文件,宏指令:S_ISSOCK()
  • Unix提供的宏指令根据st_mode成员来确定文件的类型

第六节 共享文件

  • 关于文件共享的几个相关图片,以及每种方式的流程,在课本607页。
  • 内核用三个相关的数据结构来表示其打开的文件。
  • 描述符表:表项由进程打开的文件描述符来索引的,每个打开的描述符表指向文件表中的一个表项,每个进程有其独立的描述符表。
  • 文件表:打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。包括:当前的文件位置、引用计数、以及一个指向v-node表中对应表项的指针。
  • v-node表:每个表项包含stat结构中的大多数信息,;包括st_mode和st_size成员,所有进程共享。
  • 多个描述符可以通过不同的文件表表项来引用同一个文件。 关键思想是每个描述符都有它自己的文件位置,所以对不同描述符的读操作可以从文件的不同位置获取数据。
  • 在内核删除相应文件表项之前,父子进程必须都关闭了它们的描述符。

第七节 I/O重定向

  • I/O重定向操作符,允许用户将磁盘文件和标准输入输出联系起来。unix> ls > foo.txt
  • I/O重定向是依靠dup2函数工作的。dup2函数拷贝描述符表表项oldfd到描述符表项newfd,覆盖描述符表表项newfd以前的内容。如果newfd已经打开,dup2会在拷贝oldfd之前关闭newfd。
#include <unistd.h>
int dup2(int oldfd,int newfd);

第八节 标准I/O

  • 标准I/O库将一个打开的文件模型化为一个流,也就是一个指向FILE类型的结构的指针。
#include <stdio.h>
extern FILE *stdin;  /*标准输入,文件描述符为0*/
extern FILE *stdout;  /*标准输出,文件描述符为1*/
extern FILE *stderr;  /*标准错误,文件描述符为2*/

类型为file的流是对文件描述符和流缓冲区的抽象,目的是使开销较高的Unix I/O系统调用的数量尽可能小。

本周代码托管链接

-本周代码托管链接

本周的遇到的问题

  • 在练习10.1的代码中,运行的话是没办法直接编译这个代码的,因为没有这个“csapp.h”这个头文件,所以需要下载这个头文件,在网上查阅了相关的资料,我在最后贴出解决方案的链接。

  • 通过上网查找发现csapp.h文件其实是作者自己弄的一个头文件,Linux中并不包含这个。网上说在教材配套网站http://csapp.cs.cmu.edu/public/code.html上可以下载。

  • 但是这个网站打不开……最后,我在CSDN.NET上找到了csapp.h和csapp.c,按照网上说的在csapp.h文件中#endif前加上了#include"csapp.c",并放到了/usr/lib文件夹中,并用gcc xxx.c -o xxx -lpthread语句通过了编译(因为代码中包含多线程)。

  • 其中还有一点很重要就是open和close需要小写。

  • 最后结合我在网上找到的内容,最终成功运行。

  • 第一个是没有文本的结果:

  • 第二个是有文本的结果:

其他(感悟、思考等,可选)

  • 本章的内容其实不是很多,书上只有十几页的内容,但是内容其实比较多需要理解其中的具体意思,在这里我觉得老师多次提到的常翻阅课本的好处,第一次看书的时候,我对其中的一部分还是不理解,但是在第二次再次看的时候,就明显觉得好理解很多,以练习题10.1为例子,这个题目就很好的锻炼了我们的能力,需要理解代码不说,也看到了每个问题的所在,需要自己一步步解决。
  • 并且网上可以找到很多有用的方法,有些很繁琐,而有些很简便,这都是自己在学习时候的收获。

练习题

10.1

  • 已在上面解决

10.2

  • fd1和fd2有独立的文件描述符,所以是典型的没有共享的打开文件方式
  • 它们各自有各自的描述符表、文件表、v-code表,每个描述符对于foobar.txt都有它自己的文件位置,所以它们的读取是各自独立的,
  • 从fd2的读操作会读取foobar.txt的第一个字节,因此最后得值是f,输出“c = f”

10.3

  • 子进程会继承父进程的描述符表,以及所有进程共享的同一个打开文件表。
  • 因此当子进程读取文件的第一个字节时,文件位置加一,所以父进程会读取第二个字节,输出c=o

10.4

  • 要使重定向标准输入(描述符0)到描述符5,我们可以调用dup2(5,0)或者等价的dup(5,STDIN_FILENO)

10.5

  • 因为重定向的关系fd1重定向到fd2,输出c=o

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 24篇 350小时
第一周 0/0行 1/2 20小时
第二周 53/53行 1/3 25/45小时
第三周 130/183行 1/4 30/75小时
第四周 0/183行 0/4 5/80小时
第五周 158/341行 1/5 30/110小时
第六周 84/425行 2/7 30/140小时
第七周 209/634行 1/7 30/170小时
第八周 0/634行 2/9 25/195小时
第九周 83/717行 2/11 30/225小时

注释

-深入理解计算机系统实验楼
-如何解决csapp.h的问题

posted @ 2016-11-13 17:01  20145233韩昊辰  阅读(192)  评论(1编辑  收藏  举报