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

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

教材学习内容总结

第10章 系统级I/O

10.1 Unix I/O

  1. 打开文件
    -一个应用程序通过要求内核打开相应的文件
    -描述符:内核返回一个小的非负整数
    -定义常量:
STDIN_FILENO(描述符为0)
STDOUT_FILENO(描述符为1)
STDERR_FILENO(描述符为2)
  1. 改变当前的文件位置
    -对于每个打开的文件,内核保持着一个文件位置k,初始为0
    -应用程序能够通过执行seek操作显示设置文件的当前位置为k
  2. 读写文件
    -一个读操作就是从文件拷贝n>0个字节到存储器,从当前文件位置k开始,然后将k增加到k+n
    -写操作就是从存储器拷贝n>0个字节到一个文件,从当前文件k开始,然后更新k
  3. 关闭文件
    -当应用完成了对文件的访问之后,他就通知内核关闭这个文件。

10.2 打开和关闭文件

  1. 打开文件
    (1)进程是通过调用open函数打开一个已存在的文件或者创建一个新文件:
    #include <sys/types.h>    
    #include <sys/stat.h>    
    #include <fcntl.h>    
     int open(char *filename,int flags,mode_t mode) (若成功则返回新文件描述符,若出错为-1)

注:open函数将filename转换为一个文件描述符,并且返回描述符数字。
(2)flags参数指明了进程如何访问文件,常见取值:

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

(3)mode:指定了新文件的访问权限位,符号名字如下所示:

2. 关闭文件:
-返回值:成功返回0,出错返回-1
-关闭一个已经关闭的描述符会出错
-fd:即文件的描述符

   #include <unisted.h>    
     int close(int fd)(若成功则为0,若出错则为-1)

10.3 读和写文件

  1. 读文件:read函数从描述符为fd的当前文件位置拷贝最多n个字节到存储器位置buf。返回值表示实际传送的字节数量,错误返回-1,EOF返回0。
    #include <unistd.h>
      ssize_t read(int fd, void *buf, size_t n);
  1. 写文件:write函数从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置。
    #include <unistd.h>
      ssize_t write(int fd, void *buf, size_t n);
  1. 通过调用lseek函数,应用程序可以显示地修改当前文件的位置。
  2. 某些情况下,read和write传送的字节比应用程序要求的要少,原因如下:
读时遇到EOF(end of file)
从终端读文本行
读和写网络套接字

10.4 用RIO包健壮地读写

  1. RIO包:健壮的包,会自动为你处理之前所述的不足值
  2. RIO提供两种不同函数
    (1)无缓冲的输入输出函数:这些函数直接在存储器和文件之间传送数据
    -通过调用rio_readn和writen函数
    -如果rio_readn和writen函数被一个从应用信号处理程序的返回中断,那么每个函数都会手动重启rio_readn或writen
  #include "csapp.h" 
    ssize_t rio_readn(int fd, void *usrbuf, size_t n);
    ssize_t rio_writen(int fd, void *usrbuf, size_t n);

(2)带缓冲的输入函数:这些函数允许你高效的从文件中读取文本行和二进制数据
-调用一个包装函数rio_readlineb,它从一个内部读缓冲区拷贝一个文本行,当缓冲区变空时,会自动地调用read重新填满缓冲区
-每打开一个描述符都会调用一次rio_readinitb函数
-对同一描述符,对rio_readlineb和rio_readnb的调用可以交叉进行,对这些带缓冲的函数的调用却不应和无缓冲的rio_readn函数交叉使用

    void rio_readinitb(rio_t *rp,int fd);(无返回)    
    ssize_t rio_readlineb(rio_t *rp,void *usrbuf,size_t maxlen);    
    ssize_t rio_readnb(rio_t *rp,void *usrbuf,size_n);

10.5 读取文件元数据

(1)应用程序能够通过调用stat和fstat函数,检索到关于文件的信息:元数据
-stat函数以一个文件名作为输入
-stat函数以文件描述符作为输入

    #include <unistd.h>
    #include <sys/stat.h>    
      int stat(const char *filename, struct stat *buf);
      int fstat(int fd,struct stat *buf);

-返回值:成功为0,错误为-1
(2)st_size成员包含了文件的字节数大小
(3)st_mode成员编码了文件访问许可位和文件类型
-Unix提供的宏指令根据st_mode成员来确定文件的类型

宏指令:S_ISREG()   普通文件?二进制或文本数据
宏指令:S_ISDIR()   目录文件?包含其他文件的信息
宏指令:S_ISSOCK()  网络套接字?通过网络和其他进程通信的文件

10.6 共享文件

  1. 内核用三个相关的数据结构来表示其打开的文件:
描述符表:表项由进程打开的文件描述符来索引的,每个打开的描述符表指向文件表中的一个表项,每个进程有其独立的描述符表。
文件表:打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。包括:当前的文件位置、引用计数、以及一个指向v-node表中对应表项的指针。
v-node表:每个表项包含stat结构中的大多数信息,;包括st_mode和st_size成员,所有进程共享。



10.7 I/O重定向

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

unix> ls > foo.txt

-I/O重定向是依靠dup2函数工作的。dup2函数拷贝描述符表表项oldfd到描述符表项newfd,覆盖描述符表表项newfd以前的内容。如果newfd已经打开,dup2会在拷贝oldfd之前关闭newfd。

int dup2(int oldfd,int newfd);

10.8 标准I/O和I/O函数

  1. 应用程序可以通过open、close、lseek、read、write和stat这样的函数来访问Unix I/O。
    -RIO函数:read和write的健壮的包装函数,自动处理不足值,为读文本行提供一种高效的带缓冲的方法。
    -标准I/O函数:提供了Unix I/O函数的一个更加完整的带缓冲的替代品,包括格式化的I/O例程。是磁盘和终端设备I/O之选。
  2. 套接字描述符:Unix对网络的抽象是一种称为套接字的文件类型,被称为套接字描述符。应用进程通过读写套接字描述符来与运行在其他计算机上的进程通信。
  3. 对流I/O限制是:
    -跟在输出函数之后的输入函数,必须在其中间插入fflush、fseek、fsetpos或者rewind函数,后三个函数使用Unix I/O中的lseek函数来重置当前的文件位置。
    -跟在输入函数之后的输出函数,必须在中间插入fseek、fsetpos或者rewind的调用,一个输出函数不能跟随在一个输入函数之后,除非该输入函数遇到了一个EOF。
  4. 解决对流I/O限制的方法是:
采用在每个输入操作前刷新缓存区这样的规则来满足。
对同一个打开的套接字描述符打开两个流,一个用来读,一个用来写。
对套接字使用lseek函数是非法的。
在网络套接字上,使用RIO函数更常见。

教材学习中的问题和解决过程

  1. 问题:习题10.5:read(fd1,&c,1)读取为何是o
    解决方法:在学过重定向后知道dup2(fd2,fd1)是将fd1重定向到了fd2,想着fd1fd2是打开了各自的文件所以输出也应该是f,后来发现虽然思路如此但是在重定向之前read(fd2,&c,1),已经读取了fd2的第一位,所以输出为o
  2. 问题:书上练习题10.1代码编译时头文件出错
    解决方法:csapp.h不是计算机自带的,但是可以从网上下载,open函数总是返回最低的未打开的描述符,程序的输出是fd2 = 3。
  3. 总结习题10.2
    -描述符fd1、fd2有各自的打开文件表表项
    -每个描述符对于 .txt文件都有自己的文件位置
  4. 总结习题10.3
    -子进程继承父进程的描述符表和打开文件表
    -fd在父进程中指向同一个打开文件表表项
    -子进程读取第一个字节时,文件位置加1

代码调试中的问题和解决过程

问题:一开始在使用git上传代码时,git commit所有的的代码注释后电脑突然自动关机,当我再次打开虚拟机继续上传代码时出现错误如下:

解决方法:git push -f origin +master  强行更新后,上传成功。

本周代码托管截图

代码量统计


代码托管链接:(https://git.oschina.net/yx960127/ChapterCode20145312)

学习进度条

参考资料

posted @ 2016-11-13 21:22  20145312袁心  阅读(213)  评论(0编辑  收藏  举报