2017-2018-1 20155331 《信息安全系统设计基础》第十四周学习总结

2017-2018-1 20155331 《信息安全系统设计基础》第十四周学习总结

学习目标

找出全书你认为学得最差的一章,深入重新学习一下。

学习第十章教材内容学习总结

第十章 系统级I/O

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

10.1 UnixI/O

一个Unix文件就是一个m字节的序列:

B0,B1,B2,B3,……,Bk,Bm-1

所有的I/O设备,如网络、磁盘和终端。都被模型化为文件,而所有的输入和输出都被当做对相应文件的读和写来执行。这种将设备优雅地映射为文件的方式,允许Unix内核引出一个简单、低级的应用接口,称为UnixI/O,这使得所有的输入和输出都能以一种统一且一致的方式来执行:

·打开文件

·改变当前的文件位置

·读写文件

·关闭文件

10.2打开和关闭文件

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

open函数将filename转换成一个文件描述符,并且返回描述符数字。返回的描述符总是在进程中没有打开的最小描述符。

Flags参数指明了进程打算如何访问这个文件:

?  O_RDONLY:只读

?  O_WRONLY:只写

?  O_RDWR:可读可写

Flags参数也可以是一个或者更多位掩码的或,为写提供给一些额外的指示:

? O_CREAT:如果文件不存在,就创建它的一个截断的(空)文件。

? O_TRUNC: 如果文件已经存在,就截断他。

? O_APPEN D:在每次写操作前,设置文件位置到文件的结尾处。

Mode参数指定了新文件的访问权限位。

最后进程通过调用close函数关闭一个打开的文件。

关闭一个已关闭的描述符会出错。

10.3读和写文件

#include<unistd.h>
ssize_t read(int fd,void *buf,size_t n);/*返回:若成功则为读的字数,0为EOF,-1为出错*/
ssize_ write(int fd,const void *buf,size_t n);/*返回:若成功则为写的字节数,若出错则为-1*/

1.read函数

从描述符fd的当前文件位置拷贝n个字节到存储位置buf。

2.write函数

从存储器位置buf拷贝至多个n字节到描述符fd的当前文件位置

3.lseek函数

通过调用lseek函数,应用程序能够显式地修改当前文件的位置。

△不足值

read和write传送的字节比应用程序要求的要少。

出现情况如下:

?读时遇到EOF

?从终端读文本行 (返回不足值为文本行大小)

?读和写网络套字(socket)

1.内存缓冲约束和较长的网络延迟

2.Unix管道

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

旁注:size_t是作为usigned int,而ssize_t是作为int。

在某些情况下,read和write传送的字节比应用程序要求的要少。出现这种情况的可能的原因有:

读时遇到EOF。假设该文件从当前文件位置开始只含有20个字节,而应用程序要求我们以50个字节的片进行读取,这样一来,这个read的返回的值是20,在此之后的read则返回0。

从终端读文本行。如果打开的文件是与终端相关联的,那么每个read函数将一次传送一个文本行,返回的不足值等于文本行的大小。

读和写socket。如果打开的文件对应于网络套接字,那么内部缓冲约束和较长的网络延迟会导致read和write返回不足值。

10. 4 用RIO包健壮地读写

RIO包会自动为你处理上文中所述的不足值。

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

?   无缓冲的输入输出函数。

?   带缓冲的输入函数。

10.4.1 RIO的无缓冲的输入输出函数

通过调用rio_readn和rio_writen函数,应用程序可以在存储器和文件之间直接传送数据。

注意:如果rio_readn和rio_writen函数被一个从应用信号处理程序的返回中断,那么每个函数都会手动地重启read或write。

10.4.2 rio的带缓冲的输入函数 600

?一个文本行就是一个由 换行符 结尾的ASCII码字符序列。在Unix系统中,换行符是‘\n’,与ASCII码换行符LF相同,数值为0x0a。假设我们要编写一个程序来计算文本文件中文本行的数量应该如何来实现呢?

一种方法是用read函数来一次一个字节地从文件传送到用户存储器,检查每个字节来查找换行符。这种方法的问题就是效率不高,每次取文件中的一个字节都要求陷入内核。

一种更好的方法是调用一个包装函数(rio_readlineb),它从一个内部缓冲区拷贝一个文本行,当缓冲区变空时,会自动的调用read系统调用来重新填满缓冲区。

?在带缓冲区的版本中,每打开一个描述符都会调用一次rio_readinitb函数,它将描述符fd和地址rp处的一个类型为rio_t的读缓冲区联系起来。

?rio_readinitb函数从文件rp读取一个文本行(包括结尾的换行符),将它拷贝到存储器位置usrbuf,并且用空字符来结束这个文本行。

?RIO读程序的核心是rio_read函数,rio_read函数可以看成是Unix read函数的带缓冲区的版本。当调用rio_read要求读取n个字节的时候,读缓冲区内有rp->rio_cnt个未读的字节。如果缓冲区为空的时候,就会调用read系统函数去填满缓冲区。这个read调用收到一个不足值的话并不是一个错误,只不过读缓冲区的是填充了一部分。

?一旦缓冲区非空,rio_read就从读缓冲区拷贝n和rp->rio_cnt中较小值个字节到用户缓冲区,并返回拷贝字节的数目。

?对于应用程序来说,rio_read和系统调用read有着相同的语义。出错时返回-1;在EOF时,返回0;如果要求的字节超过了读缓冲区内未读的字节的数目,它会返回一个不足值。rio_readlineb函数多次调用rio_read函数。每次调用都从读缓冲区返回一个字节,然后检查这个字节是否是结尾的换行符。

?rio_readlineb函数最多读取(maxlen-1)个字节,余下的一个字节留给结尾的空字符。超过maxlen-1字节的文本行被截断,并用一个空字符结束。

10.5 读取文件元数据

应用程序能够通过调用stat和fstat函数,检索到关于文件的信息(元数据)

#include

10. 6 共享文件

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

?  描述符表。

?  文件表。

?  V-node表。

10.7 i/o重定向 608

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

?I/O重定向的工作方式: 一种是使用dup2函数。

?dup2函数拷贝描述符表表项oldfd到描述符表表项newfd,覆盖描述符表表项newfd以前的内容。如果newfd已经打开了,dup2会在拷贝oldfd之前关闭newfd。

10.8 标准I/O

标准I/O库:

打开和关闭文件的函数fopen fclose

读和写字节的函数fgets fputs

复杂格式化的I/O函数scanf printf

流:一个流就是一个指向FILE类型结构的指针

每个ANSI C程序开始时都有三个打开流:

stdio 标准输出

stdout 标准输入

stderr 标准错误

FILE类型流是对文件描述符和流缓冲区的抽象

流缓冲区的目的:

使开销较高的Unix I/O系统调用的数量尽可能小。

课后习题总结

10.7

修改图10-5中所示的cpfile程序,使得它用RIO函数从标准输

入复制到标准输出,一次MAX-BUF个字节。

问题解答:

根据要求写得算法程序:

 #include "csapp.h"
 int main(int argc, char **argv)
 {
 int n;
 rio_t rio;
 char buf[MAXBUF];
  Rio_readinitb(&rio, STDIN_FILENO);
 while((n = Rio_readnb(&rio, buf, MAXBUF)) != 0)
Rio_writen(STDOUT_FILENO, buf, n);
 } 

解答:STDIN_FILENO属于系统API接口库,其声明为 int 型,是一个打开文件句柄,对应的函数主要包括 open/read/write/close 等系统级调用。

操作系统一级提供的文件API都是以文件描述符来表示文件。STDIN_FILENO就是标准输入设备(一般是键盘)的文件描述符。

所以所得出的结论就是:输入输出改为了键盘的输入,由屏幕输出,使用RIO输入输出提高其健壮性。

问题解决:出现的这个问题在于MAXBUF的宏定义上,因为宏定义是8192个字节,故在短短的输入一点的字符是不会有相应的输出的,将宏定义改为10就好了。

10.8

编写图10-10中的statcheck程序的一个版本,叫做fstatcheck

,它从命令行上取得一个描述符数字而不是文件名。

问题解答:

依据要求写得如下代码:

/* $begin statcheck */

#include "csapp.h"

int main (int argc, char **argv)

{

struct stat stat;

char type, readok;

/* $end statcheck */
if (argc != 2) {
fprintf(stderr, "usage: %s <filename>\n", argv[0]);
exit(0);
}
/* $begin statcheck */
fstat(atoi(argv[1]), &stat);
if (S_ISREG(stat.st_mode))     /* Determine file type */
type = "regular";
else if (S_ISDIR(stat.st_mode))
type = "directory";
else
type = "other";
if ((stat.st_mode & S_IRUSR)) /* Check read access */
readok = "yes";
else
readok = "no";

printf("type: %s, read: %s\n", type, readok);
exit(0);
 }
  /* $end statcheck */

解答:其实整个我们只需要将stat那句话改为: fstat(atoi(argv[1]), &stat);

但当然,如果需要加其他处理的话(比如判断参数对错,fd是否存在等等)。

10.9

问题解决:

Shell执行的代码应该是这样的:

  if (Fork() == 0) {/* Child */
 int fd = open("foo.txt", O_RDONLY, 0);
 dup2(fd, 1);
 close(fd);
 Execve("fstatcheck", argv, envp);
 }
时间: 2024-10-18 04:35:13

2017-2018-1 20155331 《信息安全系统设计基础》第十四周学习总结的相关文章

20135205信息安全系统设计基础第十四周学习总结

第九章 虚拟存储器 虚拟存储器的三个重要能力: 它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,高效的使用了主存. 它为每个进程提供了一致的地址空间,从而简化了存储器管理 它保护了每个进程的地址空间不被其他进程破坏. 1.物理和虚拟寻址 计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组. 每个字节都有唯一的物理地址. 第一个字节的地址为0,接下来的字节地址为1,在下一个为2,依次类推. 给定这种简单

信息安全系统设计基础第十四周学习总结

第九章  虚拟存储器 一.虚拟存储器提供了三个重要能力: 1.将主存看作是一个存储在磁盘上的地址空间的高速缓存,在主存中只保护活动的区域,并根据需要在磁盘和主存之间来回传送数据: 2.为每个进程提供了一致的地址空间,从而简化了存储器管理: 3.保护了每个进程的地址空间不被其它进程破坏. 二.理解虚拟存储器的原因: 1.虚拟存储器是中心的:它是硬件异常.硬件地址翻译.主存.磁盘文件和内核软件的交互中心: 2.虚拟存储器是强大的:它可以创建和销毁存储器片.可以映射存储器片映射到磁盘某个部分等等: 3

20135210——信息安全系统设计基础第十四周学习总结

第九章 虚拟存储器 虚拟存储器是硬件异常.硬件地址翻译.主存.磁盘文件和内核软件的完美交互,它为每个进程提供了一个大的.一致的和私有的地址空间. 通过一个很清晰的机制,虚拟存储器提供了三个重要的能力: (1)它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,它高效地使用了主存. (2)它为每个进程提供了一致的地址空间,从而简化了存储器管理. (3)它保护了每个进程的地址空间不被其他进程破坏. 9.1 物理和虚拟寻址

20135234马启扬-——信息安全系统设计基础第十四周学习总结

第九章 虚拟存储器 主要作用: 将主存看作是一个存储在磁盘上的地址空间的高速缓存,在主存中只保护活动的区域,并根据需要在磁盘和主存之间来回传送数据: 为每个进程提供了一致的地址空间,从而简化了存储器管理: 保护了每个进程的地址空间不被其它进程破坏 9.1 物理和虚拟寻址 1.物理地址 计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组,每字节都有一个唯一的物理地址PA. 根据物理地址寻址的是物理寻址. 2.虚拟地址 虚拟存储器被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成

信息安全系统设计基础第十四周学习总结——20135308

第九章 虚拟存储器 虚拟存储器的三个重要能力: 它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,高效的使用了主存 它为每个进程提供了一致的地址空间,从而简化了存储器管理 它保护了每个进程的地址空间不被其他进程破坏 第一节 物理和虚拟寻址 1.物理地址 计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组,每字节都有一个唯一的物理地址PA. 根据物理地址寻址的是物理寻址. 2.虚拟地址 虚拟存储器被组织为

2017-2018-1 20155305 《信息安全系统设计基础》第四周学习总结(课堂提交作业未来得及提交码云链接myod补充博客)

2017-2018-1 20155305 <信息安全系统设计基础>第四周学习总结(课堂提交作业未来得及提交码云链接myod补充博客) 课堂提交题目要求 编写MyOD.java 用java MyOD XXX实现Linux下od -tx -tc XXX的功能 代码码云链接补交 源代码main函数 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.

2018-2019-1 20165336《信息安全系统设计基础》第四周学习总结

2018-2019-1 20165336<信息安全系统设计基础>第四周学习总结 1.教材学到的知识点 Y86-64中程序员(汇编程序员.编译器等)可见的状态包括程序寄存器.条件码.程序状态.程序计数器(PC).内存 Y86-64中有15个程序寄存器分别是%eax %ecx %edx %ebx %esp %ebp %esi %eadi ZF SF OF PC Stat DMEM Y86-64指令支持的整数操作的长度是8字节 Y86-64的指令编码长度是1-10字节,指令编码长度从1-6个字节不等

2018-2019-1 20165214 《信息安全系统设计基础》第四周学习总结

20165214 2018-2017-1 <信息安全系统设计基础>第四周学习总结 教材学习内容总结 1.ISA的概念:一个处理器支持的指令和指令的字节级编码称为它的指令集体系结构.不同的处理器具有不同的ISA. 2.什么是冒险:一条指令的位置或操作数依赖于其他仍在流水线中的指令. 3.Y86-64有15个程序寄存器,其中%rsp被入栈.出栈.调用和返回指令座位栈指针.标志位ZF.SF.OF保存着最近的算数或逻辑指令所造成影响的有关信息. 4.Y84-64只包括8字节整数操作.指令的字节级编码需

2019-2020-1 20175320 《信息安全系统设计基础》第四周学习总结

2019-2020-1 20175320 <信息安全系统设计基础>第四周学习总结 一.教材学习内容总结 本周我们了解了在计算机系统中信息的表示与处理的方法,主要包括了以下三个方面:进制转换.位的概念与运算.信息的表示.数值运算以及信息的存储. 进制转换 进制转换已经在前面各门课程中多次提及,这里我就不再赘述了. 位的概念 该部分主要介绍了位向量的概念,并介绍了位运算以及逻辑运算,并介绍了两种移位方式,这部分需要注意的是: 注意位运算符号与逻辑运算符号的区别,以及两者计算结果数据类型的区别. 移

2018-2019-1 20165326 《信息安全系统设计基础》第四周学习总结

第四周学习总结 1.程序员可见状态 15个程序寄存器(RF) 3个条件码(CC) 程序状态(Stat) 程序计数器(PC) 内存(DMEM) 2.Y86指令 在Y86当中,寄存器也是有8个,每一个寄存器可以存储一个字,也就是一个32位二进制.条 件码是一个一位二进制的寄存器,保存着最近的算术或逻辑运算所造成的影响的信息.PC则是程序计数器,记录当前正在执行的指令的地址.存储器则是一个很大的字节数组,保存着程序和数据,Y86的程序可以使用虚拟地址(类似于数组的下标)来访问存储器,硬件和操作系统会将