zoukankan      html  css  js  c++  java
  • 20145201 《信息安全系统设计基础》第9周学习总结

    20145201 《信息安全系统设计基础》第9周学习总结

    教材学习内容总结

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

    10.1 Unix I/O
    一个Unix文件就是一个m个字节的序列:B0,B1,B2,B3...Bk...Bm-1。

    所有的输入输出都能以一种统一且一致的方式来执行:

    打开文件:一个应用程序想访问I/O设备时会要求内核打开相应的文件,内核返回一个小的非负整数,叫做描述符。
    它在后续对此文件的所有操作中标识这个文件。内核记录有关这个文件的所有信息,应用程序只需记住描述符。
    应用程序向内核发出请求→要求内核打开相应的文件→内核返回文件描述符
    
    每个进程开始时都有三个打开的文件,有三个已经被指定文件描述符:
    标准输入——0(STDIN_FILENO)
    标准输出——1(STDOUT_FILENO)
    标准错误——2(STDERR_FILENO)
    

    改变当前的文件位置:对于每个打开的文件,内核保持着一个文件位置k,初始为0,文件位置是从文件开头起始的字节偏移量。
    应用程序能够通过执行seek操作,显示的设置文件的当前位置为k。

    读写文件:读操作是从文件拷贝n>0个字节到存储器,从当前位置k开始,将k增加到k+n
    当k>=m时执行读操作会触发一个称为end-of-file(EOF)的条件,应用程序能检测到这个条件。
    写操作就是从存储器拷贝n>0个字节到一个文件,从当前位置k开始,然后更新k。
    
    关闭文件:当应用完成对文件的访问,会通知内核关闭文件。
    作为响应,内核释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中。
    无论进程因何种原因终止,内核都会关闭所有打开的文件并释放他们的存储器资源。
    
    • 打开和关闭文件
      通过调用open函数来打开一个已存在的文件或创建一个新文件.函数定义:
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    int open(char *filename,int flags,mode_t mode);
    

    返回值:类型为int型,返回的是描述符数字,总是在进程中当前没有打开的最小描述符。如果出错,返回值为-1。
    open函数将filename转换为一个文件描述符并返回。

    flags指明进程打算如何访问这个文件,可以取的值见下:

    O_RDONLY:只读
    O_WRONLY:只写
    O_RDWR:可读可写
    

    flags参数也可以是一个或更多位掩码的或:

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

    mode:指定了新文件的访问权限位,具体如下:

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

    #include <unistd.h>
    
    int close(int fd);
    
    返回:若成功则为0,若出错则为-1
    
    • 读和写文件
      应用程序是通过分别调用read和write函数来执行输入输出的:
      读:
    #include <unistd.h>
    ssize_t read(int fd,void *buf,size_t n);
    

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

    写:

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

    返回值:成功则返回写的字节数,出错返回-1。
    fd:文件描述符
    buf:存储器位置
    n:最多从存储器位置buf拷贝n个字节到当前文件位置
    需要注意的是,read和write在正常情况下返回值是实际传送的字节数量。

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

    读时遇到EOF

    从终端读文本行

    读和写网络套接字(socket)

    • 用RIO包健壮地读写

    RIO包会自动处理不足值,提供了方便、健壮和高效的I/O。

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

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

    #include "csapp.h"
    ssize_t rio_readn(int fd,void *usrbuf,size_t n);//返回:若成功则为读的字节数,若EOF则为0,若出错为-1
    ssize_t rio_writen(int fd,void *usrbuf,size_t n);//返回:若成功则为写的字节数,若出错则为-1
    
    • 带缓冲的输入函数详解

    rioreadinitb(riot *rp,int fd);
    每打开一个描述符都会调用一次该函数,它将描述符fd和地址rp处的类型为rio_t的缓冲区联系起来。

    rioreadnb(riot *rp,void *usrbuf,size_t n) ;
    从文件rp中最多读n个字节到存储器位置usrbuf。对同一描述符,rioreadnb和rioreadlineb的调用可以交叉进行。

    ssizet readlineb(riot *rp,void *usrbuf,size_t maxlen);
    从文件rp中读取一个文本行(包括结尾的换行符),将它拷贝到存储器位置usrbuf,并用空字符来结束这个文本行。

    • 读取文件元数据

    应用程序能够通过调用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.
    

    stat函数以一个文件名作为输入,并填写一个stat数据结构中的各个成员。

    • 共享文件

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

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

    文件表:所有进程共享,表项组成包括当前文件位置、引用计数、一个指向v-node表中对应表项的指针。引用计数为0时,内核会删除这个文件表表项。

    v-node表:所有进程共享,每个表项包含stat结构中的大多数信息。

    eg:两个描述符通过不同的打开文件表表项来引用两个不同的文件,没有共享

    eg:多个描述符通过不同的文件表表项来引用同一个文件.

    eg:父子进程共享相同的打开文件表集合,共享相同的文件表位置。

    • 标准I/O

    标准I/O库(libc):高级输入输出函数
    包含:
    ①fopen/fclose:打开和关闭文件
    ②fread/fwrite:读和写字节
    ③fgets/fputs:读和写字符串
    ④scanf/printf:复杂格式化的I/O函数

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

    每个程序开始时都有三个打开的流:
    ①stdin:标准输入
    ②stdout:标准输出
    ③stderr:标准错误

    它们对应于标准输入、标准输出和标准错误 ,定义如下:

    #include <stdio.h>
    extern FILE *stdin;
    extern FILE *stdout;
    extern FILE *stderr;
    

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

    教材学习中的问题和解决过程

    问题1:在:wq保存文件时出现了下面的问题:

    查阅资料发现是因为这个文件需要root权限才能编辑,之前只是普通用户,忘了使用用sudo启动。用权限打开sudo vim 文件名打开文件之后再编译。

    问题2 书p603rio_read函数中,erro!=EINTR为何是被应用信号处理程序的返回中断?是否应该是erro==EINTR

    本周代码托管截图

    代码链接

    其他(感悟、思考等,可选)

    本章主要是帮助我们理解系统级的输入输出,对文件的打开和关闭、读和写等操作又有了更深的理解。Unix I/O,告诉我们虽然我们有一些高级的标准库函数可以使用,但是在一些情况下,比如网络套接字时,必须使用系统级I/O。
    本章在阅读代码上花费了较多时间,理解起来不是很容易。

    学习进度条

    代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
    目标 5000行 30篇 400小时
    第一周 100/100 2/2 25/25 安装了虚拟机并学习掌握核心的linux命令
    第二周 100/200 1/3 30/55 虚拟机上的C语言编程
    第三周 150/350 1/4 10/65 计算机中信息的表示和运算
    第四周 0/350 0/4 3/68 复习前几周内容
    第五周 75/420 1/5 20/88 程序的机器级表示
    第六周 125/545 1/6 20/108 Y86指令 硬件语言控制HCL
    第七周 72/617 1/7 20/128 磁盘 存储器相关结构
    第八周 0/617 2/9 20/148 期中总结
    第九周 185/802 2/11 25/173 系统级的输入输出

    参考资料

  • 相关阅读:
    github
    保存中文文本
    python3与 python2 urllib模块区别
    gitbook 使用粘自csdn
    html基础
    R语言学习笔记之十
    R语言学习笔记之九
    R语言学习笔记之八
    R语言学习笔记之七
    R语言学习笔记之六
  • 原文地址:https://www.cnblogs.com/20145201lzx/p/6044064.html
Copyright © 2011-2022 走看看