zoukankan      html  css  js  c++  java
  • 第九周学习总结

    第十章 系统级I/O

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

    • ANSI C提供了标准I/O库——printf和scanf这样带缓冲区的I/O函数。
    • C++中有重载操作符>>(输出)和<<(输入)提供了类似的功能。
    • Unix系统中,是通过使用由内核提供的系统级Unix I/O函数来实现的。

    学习系统级I/O,也就是Unix I/O的原因是:

    • 了解Unix I/O将帮助你理解其他的系统概念
    • 有时你除了使用Unix I/O以外别无选择

    10.1 Unix I/O

    所有的I/O设备,如磁盘,网络,终端,都被模型化为文件。

    • 打开文件。一个应用程序通过要求内核打开相应的文件。文件打开后,应用程序记录描述符,内核记录所有和文件相关的信息。
      • 每个进程开始的时候都有3个打开的文件:标准输入0,标准输出1,标准错误2。
    • 改变当前的文件位置。对于每个打开的文件,内核记录其所有相关的信息,其中一个是文件位置k,初始为0。从文件开头起始的字节偏移量。
    • 读写文件。一个读操作就是从文件拷贝n>0个字节到存储器,从当前文件位置k开始,然后将k增加到k+n。给定的一个大小为m字节的文件,当k>=m时,执行读操作会触发一个称为EOF的条件,应用程序能检测到这个条件。写操作就是从存储器拷贝n>0个字节到一个文件,从当前文件k开始,然后更新k。
    • 关闭文件——应用程序通知内核关闭文件。内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。

    10.2 打开和关闭文件

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

    int open(char *filename, int flags, int mode);
    

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

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

    当进程通过带某个mode参数的open函数调用来创建一个新文件时,文件的访问权限位被设置为mode & ~umask。

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

    int close(int fd);
    

    10.3 读和写文件

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

    ssize_t read(int fd, void *buf, size_t n);
    ssize_t write(int fd, const void *buf, size_t n);
    

    read函数调用返回有三种情况:

    • 返回值-1表示一个错误。
    • 返回值0表示EOF。
    • 返回值表示的是实际传送的字节数。

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

    在某些情况下,read和write传送的字节比应用程序要求的要少。这些不足值不表示有错误。出现这种情况的原因如下:

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

    10.4 用RIO包健壮地读写

    Robust I/O,RIO提供了两类不同的函数:

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

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

    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或write。

    RIO的带缓冲的输入函数:

    rio_readnb

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

    RIO读程序的核心是rio_read的函数。rio_read函数时Unix read函数带缓冲的版本。

    10.5 读取文件元数据

    文件的元数据,就是关于文件的信息。

    int stat(const char *filename, struct stat *buf);
    int fstat(int fd, struct stat *buf);
    

    讨论Web服务器时,会需要stat数据结构中的st_mode和st_size成员。st_mode则编码了文件访问许可位和文件类型。

    Unix提供的宏指令根据st_mode成员来确定文件的类型。

    • S_ISREG() 普通文件
    • S_ISDIR() 目录文件
    • S_ISSOCK() 套接字

    10.6 共享文件

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

    • 描述符表。是每个进程都有的。每个条目是由文件描述符索引的,条目值指向文件表中的一项。
    • 文件表。是所有进程共享的。条目包含一个文件的当前位置,引用计数,以及一个指向v-node表中对应表项的指针。
    • v-node表。是所有进程共享的。包含了stat结构中的大多数信息,包括st_mode和st_size成员。

    一次open,将在文件表中建立一个新的条目,将在描述符表中建立一个新的描述符指向这个文件表中的条目。

    如果已open之后,进程fork了,那么父子进程都拥有相同的描述符内容,指向的也会是文件表中相同的条目,也就是共享了该文件的当前位置。

    两次open同一个文件,虽然是同一个文件,但是有两个描述符条目,指向的也是文件表中的两个条目,虽然文件表中的两个条目指向v-node表中的一个条目,但是,文件表两个条目是关键。

    10.7 I/O重定向

    I/O重定向的一个方式是使用dup2函数。

    int dup2(int oldfd, int newfd);
    

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

    10.8 标准I/O

    ANSI C定义了一组高级输入输出函数,称为标准I/O库。

    标准I/O库将一个打开的文件模型化为一个流。对于程序员而言,一个流就是一个指向FILE类型的结构的指针。

    类型为FILE的流是对文件描述符和流缓冲区的抽象。流缓冲区的目的和RIO读缓冲区的一样:就是使开销较高的Unix I/O系统调用的数量尽可能的小。

    参考内容:

    课本,百度百科。

  • 相关阅读:
    常量
    html5+css3 background-clip 技巧
    AJAX小结
    使用jquery来完成AJAX操作
    linux命令 cp 递归复制 带权限复制
    html标记语言 --超链接
    html标记语言 --图像标记
    html标记语言 --文本标记
    [转]linux如何修改文件或目录的权限(chmod)
    html标记语言 --格式标记
  • 原文地址:https://www.cnblogs.com/lxq20135309/p/4947734.html
Copyright © 2011-2022 走看看