• 信息安全系统设计基础 第9周学习笔记


    系统级I/O

    10.1 Unix I/O

    • 一个unix文件就是一个m字节的序列(b0b1b2...bm-1)。

      所有的IO设备,如网络,磁盘,终端,都被模型化为文件,而所有的输入和输出都被当作对相应文件的读和写来执行。

    10.2 打开和关闭文件

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

      • 打开标志flags有三种基本标志:O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(可读可写)。

      • 也可以和其他三种(O_CREAT、O_TRUNC、O_APPEND)组合使用。

         O_CREAT:如果文件不存在,就创建它的一个截断的(空的)文件。
        
         O_TRUNC:如果文件已经存在,就截断它。
        
         O_APPEND:在每次写操作前,设置文件位置到文件的结尾处。
        

    10.3 相关函数

    • open、close、read、write。具体定义可以参见man手册。

      • 某些情况下,原始的read,write传送的字节比应用程序要求的要少,这些不足值(short count)不一定是错误(意为,比如read函数参数要读5个字节,结果只读了3个字节,即小于5),下面的情况下将可能发生不足值:

          读时遇到EOF。
        
          从终端读文本行。
        
          读和写网络套接字。
        

    10.4 用RIO包健壮地读写

    • 这个包会处理上面的不足,RIO提供了方便、健壮和高效的I/O。提供了两类不同的函数:

      • 无缓冲的输入输出函数 直接在存储器和文件之间传送数据,没有应用级缓冲,它们对将二进制数据读写到网络和从网络读写二进制数据尤其有用。

      • 带缓冲的输入函数

          ssize_t rio_readn(int fd,void *usrbuf,size_t n);
        
          ssize_t rio_writen(int fd,void *usrbuf,size_t n);
        
    • 对同一个描述符,可以任意交错地调用rio_readn和rio_writen。一个问本行的末尾都有一个换行
      符,那么像读取一个文本中的行数怎么办,使用read读取换行符这个方法不是很妥当,可以调用一个包装函数(rio_readineb),它从一个内部读缓冲区拷贝一个文本行,当缓冲区为空时,会自动地调用read重新填满缓冲区。也就是说,这些函数都是缓冲区操作而言的。

    • 函数是线程安全的:它在同一个描述符上可以被交替地调用。

    10.5 读取文件元数据

    • 元数据:关于文件的信息,如创建时间,修改时间,metadata。可以调用stat,fstat函数。

    • 文件类型:

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

    10.6 共享文件

    • 内核用三种相关的数据结构来表示打开的文件。

      • 描述符表:它的表项由进程打开的文件描述符来索引的。

      • 文件表:打开文件的集合是一张文件表来表示的,所有的进程共享这张表。

      • v-node表:同文件表一样,所有的进程共享这张v-node表。每个表项包含stat结构中的大部分信息,如文件大小等。

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

    10.7 I/O重定向

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

        unix > ls > foo.txt
      
        实际是dup2函数(one case)。dup2函数对文件描述符表项进行重定位。
      

    10.8 标准I/O

    • 标准函数如fopen,fclose,fread,fwrite,fgets,fputs,scanf,printf。

    • 标准IO库将一个打开的文件模型化为一个流,对于程序员来说,一个流就是一个指向类型为FILE结构的一个指针。每个ANSI C程序开始都有三个打开的流stdin,stdout,stderr,分别对应于标准输入、输出、错误。

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

    • 标准I/O流,从某种意义上而言是全双工的,因为程序能够在同一个流上执行输入和输出。但是有一些限定:

      • 限定1:输入函数跟有输出函数之后。如果中间没有fflush,fseek,fsetpos或rewind的调用,一个输入函数不能跟随在一个输出函数之后。fflush清空与流相关的缓冲区,后三个函数使用unix IO lseek函数来重置当前文件的位置。

      • 限定2:输出函数跟有输入函数之后。情况类同上。
        这些限定给网络应用带来一个问题:因为对套接字使用lseek是非法的。用Rio包可以解决这个问题。用sprintf把输出格式化一个字符串,通过rio_writen输出,傅rio_readlineb来读一行,用scanf来从文本中提取不同的字段。

    参考资料:

    • 深入理解计算机系统(第二版)pdf

    • 深入理解计算机系统笔记,系统级I/O

    读书小结

    • Unix内核使用三个相关的数据结构来表示打开的文件。描述符表中的表项指向打开文件表中的表项,而打开文件表中的表项又指向v-node表中的表项。每个进程都有它自己单独的描述符表,而所有的进程共享同一打开文件表和v-node表。

    • 有一些代码还存在不明白的地方。

  • 相关阅读:
    SQL Server 百万级数据提高查询速度的方法(转)
    sql优化的几种方法
    MyBatis中调用存储过程和函数
    android ipc通信机制之二序列化接口和Binder
    APK的目录结构
    android Handler错误,不同的包Handler
    BaiduMap开发,获取公交站点信息。
    GitHub托管项目步骤
    Mysql,JDBC封装
    简单工厂模式练习
  • 原文地址:https://www.cnblogs.com/whyfarrell/p/4948027.html
Copyright © 2020-2023  润新知