zoukankan      html  css  js  c++  java
  • 信息安全系统设计基础第九周学习总结——20135308

    第十章 系统级I/O

    10.1 unix i/o 596

    一个Unix文件就是一个m个字节的序列,所有的I/O设备都被模型化为文件,而所有的输入和输出都被当做对应文件的读和写来执行。这被称为UnixI/O,使得所有的输入和输出能以一种统一且一致的方式来执行:

    1、打开文件

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

    Unix外壳创建的每个进程开始时都有三个打开的文件:

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

    2、改变当前的文件位置

    对于每个打开的文件,内核保持着一个文件位置k,初始为0。这个文件位置是从文件开头起始的字节偏移量。通过执行seek操作设置文件位置为k。

    3、读写文件

    (1)读操作

    读操作就是从文件拷贝n>0个字节到存储器,并且改变文件当前位置。(如果当前位置是k,则改变为k+n) EOF的来源: 文件结尾处没有明确的EOF信号,是当文件当前位置的数值超过了文件大小时,会处罚一个称为end-of-file的条件,能够被应用程序检测到,这就是所谓的EOF信号。

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

    10.2 打开和关闭文件

    • open函数将filename转换为一个文件描述符,并且返回描述符数字。

    打开一个已存在的文件或者创建一个新文件:

    #include <sys/types.h>
    
    #include <sys/stat.h>
    
    #include <fcntl.h>
    
    
     int open(char *filename,int flags,mode_t mode) (若成功则返回新文件描述符,若出错为-1)
    

      

    • flags参数指明了进程如何访问文件,常见取值:

      ORDONLY:只读 OWRONLY:只写 ORDWR:可读可写 一个或者更多位掩码的或 OCREAT:文件不存在,就创建新文件 OTRUNC:如果文件存在,就截断它 OAPPEND:写操作前设置文件位置到结尾处

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

    • 关闭一个打开的文件:

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

        

    返回值:成功返回0,出错返回-1 关闭一个已经关闭的描述符会出错

    fd:即文件的描述符。

    10.3 读和写文件

    • 读文件:read函数从描述符为fd的当前文件位置拷贝最多n个字节到存储器位置buf。返回值表示实际传送的字节数量,错误返回-1,EOF返回0。

      #include <unistd.h>
      ssize_t read(int fd, void *buf, size_t n);
      
    • 写文件:write函数从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置。

      #include <unistd.h>
      ssize_t write(int fd, void *buf, size_t n);
      
    • 通过调用lseek函数,应用程序可以显示地修改当前文件的位置。

    • 出现不足值(指在某些情况下,read和write传送的字节比应用程序要求的要少)的原因:

        1.读的时候遇到EOF:文件末尾剩余的字节数不足读取文件的字节片大小。

        2.从终端读文本行:若打开文件与终端相关联,则每个read函数将一次传送一个问本行。返回的不足值等于文本行的大小。

        3.读和写socket:若打开的文件对应于网络套接字,那么内部缓冲约束和较长的网络延迟会引起read和write返回不足值。

    10.4 用RIO包健壮地读写

    1、RIO的无缓冲的输入输出函数

    rioreadn函数和riowriten函数,应用程序可以在存储器和文件之间直接传送数据:

    #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);
    

      

    若成功则返回传送成功的字节数,若EOF则为0(只对rio_readn而言),若出错 则为-1。

    2.RIO的带缓冲的输入函数

    rio_ readlineb和rio_readnb函数从一个内部读缓冲区拷贝一个文本行,当缓冲区变空时,会自动调用read重新填满缓冲区。

    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);
    

      

    若成功则返回传送成功的字节数,若EOF则为0,若出错 则为-1。

    打开每一个描述符都会调用一次rioreadinitb函数,他将描述符fd和地址rp处的一个类型为riot的读缓冲区联系起来。

    10.5 读取文件元数据

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

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

    返回值:成功为0,错误为-1

    st_size:包含文件的字节数大小

    st_mode:包编码文件访问许可位和文件类型。

    • 普通文件包括某种类型的二进制或文本数据。

    • 目录文件包含关于其他文件的信息。

    • 套接字是一种用来通过网络与其他进程通信的文件。

    10.6 共享文件

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

    • 描述符表:表项由进程打开的文件描述符来索引的,每个打开的描述符表指向文件表中的一个表项,每个进程有其独立的描述符表。

    • 文件表:打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。包括:当前的文件位置、引用计数、以及一个指向v-node表中对应表项的指针。

    • v-node表:每个表项包含stat结构中的大多数信息,;包括stmode和stsize成员,所有进程共享。

    参考资料

    1.《深入理解计算机系统》教材

    2.小组问题:第十章关于csapp.h的提问 http://group.cnblogs.com/topic/73278.html

    实践项目

    首先把老师的压缩包在虚拟机中解压缩,运行每个代码

    1、cp的作用就是读取一个文件的内容到存储器,在新的地址创建空白文件,再从存储器将内容写入新文件。(如下图把ls1.c复制,存为lc.c文件)

    2、ls1程序的作用是在当前目录显示文件名(未带参数直接显示,带参数的存入argc)

    3、ls2不仅显示了文件名,还用来显示文件的详细信息,比如用户名、群组名、大小、创建时间、读写权限等。

    4、echostate代码用来检查命令行中的提示符是否显示的,如果显示,输入的命令都可见,不显示则表示输入的命令不可见。

    5、fileinfo代码这个功能用来实现显示文件信息,建立了一个stat数据结构。先判断命令是否有操作数,有的话才能继续进行下去,如果没有报错就打印出来相关文件信息,报错就用perror将报错信息打印出来。

    6、filesize代码用st_size成员来计算文件的字节数大小,gcc后有一个警告,调用正常。

    7、setecho代码用来改变echo状态。

    8、spwd代码的功能是列出当前目录。

    9、testioctl代码用来显示当前文件的大小

    习题筛选:

    10.1

    1、首先,建立相关文件10-1.c、foo.txt、baz.txt

    2、将娄老师开学时上传的CSAPP.2nd.code文件解压至虚拟机中,从中找到libcsapp32.a静态库文件、csapp.h、csapp.c,把它们放在10-1.c所在的Terminal的主文件夹中。因为虚拟机为32位,.c文件中才是定义的那些函数的具体实现。

    3、接下来,把csapp.c生成静态库libcsapp.a,它相当于main函数,这样可以直接使用,运行习题代码。

    4、因为csapp.c中有关于线程的头文件,所以需要加上-lpthread,这个命令是使其连接csapp.h来调用csapp.c,来运行代码10-1.c,得出结果fd2 = 3。

  • 相关阅读:
    String和StringBuilder和StringBuffer
    多态
    组件
    反向代理
    基础知识
    reflection
    v-model 与 v-bind:model
    tomcat端口占用问题
    socket
    简要概括内存机制
  • 原文地址:https://www.cnblogs.com/bonjourvivi/p/4947891.html
Copyright © 2011-2022 走看看