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 |