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

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

教材学习内容总结:

第十章:

第一节:Unix I/O:

1.打开文件:

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

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

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

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

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

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

2.读写文件

(1)读

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

※EOF的来源:

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

(2)写

写操作是从存储器拷贝n>0个字节到一个文件,然后更新当前文件位置。

3.关闭文件

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

第二节 打开和关闭文件

1.open函数

  • O_RDONLY:只读
  • O_WRONLY:只写
  • O_RDWR:可读可写
  • O_CREAT:文件不存在,就创建新文件
  • O_TRUNC:如果文件存在,就截断它
  • O_APPEND:写操作前设置文件位置到结尾处

mode:指定了新文件的访问权限位

2.close函数

第三节 读和写文件

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

  • ssize_t read(int fd,void *buf, size_t n);
  • ssize_t write(int fd, const void *buf,size_t n);

某些情况下,read和write传送的字节比应用程序要求的要少,原因如下:

  • 读时遇到EOF(end of file)
  • 从终端读文本行
  • 读和写网络套接字

第四节 用RIO包健壮的读写

RIO包:健壮的包,会自动为你处理之前所述的不足值

RIO提供两种不同函数

  • 无缓冲的输入输出函数:这些函数直接在存储器和文件之间传送数据

通过调用rio_readn和writen函数

如果rio_readn和writen函数被一个从应用信号处理程序的返回中断,那么每个函数都会手动重启rio_readn或writen

  • 带缓冲的输入函数:这些函数允许你高效的从文件中读取文本行和二进制数据

调用一个包装函数rio_readlineb,它从一个内部读缓冲区拷贝一个文本行,当缓冲区变空时,会自动地调用read重新填满缓冲区

每打开一个描述符都会调用一次rio_readinitb函数

对同一描述符,对rio_readlineb和rio_readnb的调用可以交叉进行,对这些带缓冲的函数的调用却不应和无缓冲的rio_readn函数交叉使用

第五节 读取文件元数据

元数据即文件信息,需要用到的函数是stat和fstat。定义如下:

#include <unistd.h>
#include <sys/stat.h>
int stat(const char *filename, struct stat *buf);
int fstat(int fd,struct stat *buf);
  • stat函数以一个文件名作为输入,填写一个stat数据结构中的各个成员。
  • fstat函数以文件描述符而不是文件名作为输入。
  • st_ size成员包含了文件的字节数大小。
  • st_ mode成员则编码了文件访问许可位和文件类型

第六节 共享文件

内核用三个相关的数据结构来表示打开的文件:

  • 描述符表
  • 文件表:打开文件的集合是由一张文件表来表示的。
  • v-node表

通过不同的打开文件表表项来引用两个不同的文件《没有共享文件,每个描述符对应一个不同的文件

多个描述符也可以通过不同的文件表表项来引用同一个文件

父子进程共享文件

第七节 I/O重定向

I/O重定向操作符: >

ls > foo.txt
这句代码的含义就是使外壳加载和执行ls程序,并且将标准输出重定向到磁盘文件foo.txt。

I/O重定向函数: dup2

函数定义为:

#include <unistd.h>
int dup2(int oldfd, int newfd);

返回值:成功返回描述符,错误返回-1

这个函数执行的操作是,拷贝描述符表表项oldfd,覆盖描述表表项newfd,如果后者被打开,则在拷贝前关闭它。

第八节 标准I/O

标准I/O库:

ANSI C定义了一组高级输入输出函数,称为标准I/O库,包含:

fopen、fclose,打开和关闭文件
fread、fwrite,读和写字节
fgets、fputs,读和写字符串
scanf、printf,复杂的格式化的I/O函数
2.流——类型为FILE的流是对文件描述符和流缓冲区的抽象

标准I/O库将一个打开的文件模型化为一个流。

教材学习中遇到的问题:

习题10.1:

open函数返回值:若成功则为新文件的描述符,若出错则为-1

在每个进程开始时都会打开三个文件:标准输入、标准输出、标准错误。它们的描述符分别为0、1、2。因此,fd1返回的描述符为3。之后调用了close函数,释放描述符3。所以fd2的返回值也就是描述符为3

习题10.2:

这道题对应图10-12。fd1和fd2对应不同的描述符表,也对应不同的文件表项,但是它们对应的v-note表一样,都是打开foobar.txt。因此读foobar的第一个字节,输出f

习题10.3:

这道题对应图10-13。我理解的是子进程就相当于对父进程的复制,因此父进程中描述符表、文件表项、v-note表对应关系和子进程中完全一样。描述符fd在父子进程中指向同一个文件表项。因此子进程读完后,父进程读到的为o,输出o

习题10.4:

dup2(A,B)指将B重新定向到A,也是把A拷贝到B

标准输入的描述符为0

习题10.5:

dup2(fd2,fd1)将fd2拷贝到fd1,fd1被重新定向为fd2。所以再次执行read后,输出为o

代码中遇到的问题:

就是没有csapp.h的问题,已经发到答疑论坛。在卢肖明同学的帮助下得以解决。

https://group.cnblogs.com/topic/75886.html

代码托管:

https://git.oschina.net/20144303sys/work

总结和感悟:

这周学习的内容跟前几周比起来算比较少的。RIO包那里理解的不是很透彻,其他的像描述符、返回值、共享文件、重定向那里的知识结合习题已经掌握了。另外主要是代码的实践中出现了一些问题,通过百度没能解决头文件csapp.h的问题,后来把出现的问题发到了答疑论坛里,学习了论坛里其他同学的解决办法,最终还是成功的把代码运行了。以后要更多的运用答疑论坛,通过这次的使用发现自己遇到的问题很可能其他同学也遇到了,可以在论坛中共同学习、相互帮助,也能减少时间的浪费。

学习进度条:

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 0/0 1/1 20/20
第二周 300/300 1/2 20/40
第三周 300/600 1/3 20/60
第五周 200/800 2/5 20/80
第六周 100/900 2/7 20/80
第七周 160/1060 1/8 20/100
第八周 0/1060 2/9 20/120
第九周 210/1270 2/11 20/140
posted @ 2016-11-13 21:03  20144303石宇森  阅读(154)  评论(2编辑  收藏  举报