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

    一、学习目标

    1. 掌握系统编程和系统调用的概念
    2. 掌握系统编程错误处理的方式
    3. 掌握Unix/Linux系统级I/O:open close read write seek stat
    4. 掌握RIO
    5. 掌握I/O重定向的方法

    参考博客:闫佳歆

    参考资料:课本


    二、学习资源

    1. 教材:附录A,第10章《系统级I/O》
    2. 课程资料:https://www.shiyanlou.com/courses/413 实验11,课程邀请码:W7FQKW4Y
    3. 教材中代码运行、思考一下,读代码的学习方法见这。

    三、学习方法

    1. 进度很重要:必须跟上每周的进度,阅读,练习,问答,项目。我会认真对待每一位同学,请你不要因为困难半途而废。
    2. 问答很重要:遇到知识难点请多多提问,这是你的权利更是您对自己负责的义务。问答到博客园讨论小组:http://group.cnblogs.com/103791/
    3. 实践很重要:解决书中习题,实践书中实例,完成每周项目,才算真的消化了这本好书。通过实验楼环境或自己安装的虚拟机在实践中进行学习
    4. 实验报告很重要:详细记录你完成项目任务的思路,获得老师点评和帮助自己复习。学习完成后在博客园中(http://www.cnblogs.com/)把学习过程通过博客发表,博客标题“信息安全系统设计基础第九周学习总结”

    四、学习任务

    1. 阅读教材,注意每个系统调用的参数、返回值,会查帮助文档
    完成课后练习(书中有参考答案)重点:10.1、10.2、10.3、10.4、10.5
    2.重要命令:
    man -k key1 | grep key2| grep 2 : 根据关键字检索系统调用
    grep -nr XXX /usr/include :查找宏定义,类型定义
    3. 考核:教材内容,练习题把数据变换一下
    4. 实验:需要动手的到实验楼中练习一下

    五、后续学习预告

    (可选):教材第八章《异常控制流》

    六、学习过程

    第十章 系统级I/O

    输入/输出(I/O)是在主存外部设备之间拷贝数据的过程。

    10.1 Unix I/O

    这一节涉及到操作系统的基本抽象之一——文件。也就是说,所有的I/O设备都被模型化为文件,而所有的输入输出都被当做对相应文件的读/写。相关的执行动作如下:

    1.打开文件:

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

    • 文件描述符:一个小的非负整数,用来在后续对此文件的所有操作中标识这个文件。有三个已经被指定了的如下:

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

      括号中是常量表示形式,使用时需要加头文件

    也就是说,在Unix生命周期一开始,0、1、2就被占用,以后的open只能从3开始——习题10.1.

    在UNIX下还有stdin,stdout,stderr表示同样的含义。

    二者的主要区别为:

    1.数据类型不同,前者为int类型,后者为FILE*;

    2.STDIN_FILENO主要用在read(),write()等中,后者主要用在fread(),fwrite()以f开头。

    2.改变当前的文件位置

    通常,读,写操作都从当前文件偏移量处开始(也就是文件位置),并使偏移量增加所读写的字节数,可以理解为光标所在的位置。

    当打开一个文件的最初时候文件的偏移量为0.

    通过seek操作,可以显示的设置文件的当前位置为k。

    3.读写文件

    (1)读

    读操作就是从文件拷贝n>0个字节到存储器,并且改变文件当前位置。(如果当前位置是k,则改变为k+n)

    ※EOF的来源:

    这里有一个一直以来的理解上的误区:文件结尾处没有明确的EOF信号,是当文件当前位置的数值超过了文件大小时,会处罚一个称为end-of-file的条件,能够被应用程序检测到,这就是所谓的EOF信号。

    (2)写

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

    4.关闭文件

    应用通知内核关闭文件→内核释放文件打开时的数据结构→恢复描述符→释放存储器资源。

    10.2 打开和关闭文件

    1.open函数

    (1)函数定义:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int open(char *filename, int flags, mode_t mode);

    (2)参数解析:

    • 返回值:类型为int型,返回的是描述符数字,总是在进程中当前没有打开的最小描述符。如果出错,返回值为-1.
    • filename:文件名
    • flags:指明进程打算如何访问这个文件,可以取的值见下:

      O_RDONLY:只读
      O_WRONLY:只写
      O_RDWR:可读可写
      
      O_CREAT:文件不存在,就创建新文件
      O_TRUNC:如果文件存在,就截断它
      O_APPEND:写操作前设置文件位置到结尾处
      这些值可以用连接起来。
    • mode:指定了新文件的访问权限位,符号名称如下:

    2.close函数

    (1)函数定义:

    #include <unistd.h>
    
    int close(int fd);

    (2)参数解析:

    • 返回值:成功返回0,出错返回-1

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

    • fd:即文件的描述符。

    10.3 读和写文件

    1.读 read

    (1)函数原型:

    #include <unistd.h>
    
    ssize_t read(int fd, void *buf, size_t n);

    (2)参数解析:

    • 返回值:成功则返回读的字节数,EOF返回0,出错返回-1。返回值为有符号数。
    • fd:文件描述符
    • buf:存储器位置
    • n:最多从当前文件位置拷贝n个字节到存储器位置buf

    2.写 write

    (1)函数原型:

    #include <unistd.h>
    
    ssize_t write(int fd, void *buf, size_t n);

    (2)参数解析:

    • 返回值:成功则返回写的字节数,出错返回-1。返回值为有符号数。
    • fd:文件描述符
    • buf:存储器位置
    • n:最多从存储器位置buf拷贝n个字节到当前文件位置

    需要注意的是,read和write在正常情况下返回值是实际传送的字节数量。

    3.通过lseek函数可以显式的修改当前文件的位置

    4.不足值

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

    • 读的时候遇到EOF
    • 从终端读文本行
    • 读和写socket

    10.4 用RIO包健壮的读写

    RIO,Robust I/O,针对的出现不足值的问题。

    1.RIO的无缓冲的输入输出函数。

    这些函数的作用是直接在存储器和文件之间传送数据,常适用于网络和二进制数据之间。

    rio_readn函数和rio_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);

    参数:

    • fd:文件描述符
    • usrbuf:存储器位置
    • n:传送的字节数
    • 返回值:

      rio_readn成功则返回传送的字节数,EOF为0(一个不足值),出错为-1
      rio_writen成功则返回传送的字节数,出错为-1,没有不足值。

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

      可以高效的从文件中读取文本行和二进制数据。

    一个概念:一个文本行就是一个由换行符结尾的ASCII码字符序列。

    范例:如何统计文本文件中文本行的数量——通过计算换行符。需要用到的函数:

    #include "csapp.h"
    
    void rio_readinitb(rio_t *rp, int fd);//将描述符fd和地址rp处的一个类型为rio_t的读缓存区联系起来。
    
    ssize_t rio_readlineb(rio_t *rp,void *usrbuf, size_t maxlen);//从文件rp中读出一个文本行,包括换行符,拷贝到存储器位置usrbuf,并用空字符结束这个文本行。最多赌到maxlen-1个字节,最后一个给结尾的空字符。
    ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);//从文件rp中读取最多n个字符到存储器位置usrbuf中。
    
    成功则返回传送的字节数,EOF为0,出错为-1。

    先连接标准输入和地址rio,再根据返回值判断是否成功将rio中的一行内容拷贝到了buf中,如果是再把这一行拷贝到标准输出中,即可实现一次一行的从标准输入拷贝一个文本文件到标准输出。

     

    10.5 读取文件元数据

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

      #include <unistd.h>
      #include <sys/stat.h>
      
      int stat(const char *filename,struct stat *buf);
      int fstat(int fd,struct stat *buf);
    • st _ size成员包含了文件的字节数大小。st _ mode成员则编码了文件访问许可位和文件类型。

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

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

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

    10.6 共享文件

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

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

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

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

    10.7 I/O重定向

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

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

    #include <unistd.h>
    
    int dup2(int oldfd,int newfd);

    10.8 标准I/O

    标准I/O库将一个打开的文件模型化为一个流,也就是一个指向FILE类型的结构的指针。

    #include <stdio.h>
    extern FILE *stdin;  /*标准输入,文件描述符为0*/
    extern FILE *stdout;  /*标准输出,文件描述符为1*/
    extern FILE *stderr;  /*标准错误,文件描述符为2*/

    类型为file的流是对文件描述符和流缓冲区的抽象,目的是使开销较高的Unix I/O系统调用的数量尽可能小

  • 相关阅读:
    Log4Net二次封装
    jquery动态生成二维码添加自定义logo
    小程序map地图多点定位
    vue上传阿里云图片组件
    vue移动端地址三级联动组件(二)
    vue移动端地址三级联动组件(一)
    vue自定义轻量级form表单校验
    js中间件
    事件模型
    通过JS唤醒app(安卓+ios)
  • 原文地址:https://www.cnblogs.com/20135213lhj/p/4948500.html
Copyright © 2011-2022 走看看