• 2017-2018-1 20155320 《信息安全系统设计基础》第十四周学习总结


    2017-2018-1 20155320 《信息安全系统设计基础》第十四周学习总结

    参考老师提供的教材内容导读

    本周的内容是要找出全书你认为学得最差的一章,深入重新学习一下

    我决定学习第十章——系统级I/O,因为对相关内容感觉再应用方面并未十分熟练。

    教材学习内容总结

    10.1 Unix I/O

    • Linux文件:m个字节的序列
    • 所有的I/O设备都被模型化为文件,所有的输入和输出都被当作对相应文件的读和写来执行
    • Linux内核引出一个简单、低级的应用接口,称为Unix I/O,这使得所有的输入和输出都能以一种统一且一致的方式来执行

    10.2 文件

    • 每个Linux文件都有一个类型来表明它在系统中的角色:
      普通文件包含任意数据。

      目录是包含一组链接的文件,其中每个链接都将一个文件名映射到一个文件,这个文件可能是另一个目录。每个目录至少含有两个条目:'.'是到该目录自身的链接,'..'是到目录层次结构中父目录的链接。

      套接字是用来与另一个进程进行跨网络通信的文件。

    • 用cd命令来修改shell中的当前工作目录

    • 路径名有两种形式:
      绝对路径名以一个斜杠开始,表示从当前工作目录开始的路径

      相对路径名以文件名开始,表示从当前工作目录开始的路径

    10.3 打开和关闭文件

    • 进程通过open函数来打开一个已存在的文件或者创建
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int open(char *filename, int flags, mode_t mode);
    若成功则返回新的文件描述符,若出错则为1
    
    1. 参数解析:

      返回值:类型为int型,返回的是描述符数字,总是在进程中当前没有打开的最小描述符。如果出错,返回值为-1.

      filename:文件名

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

    以下值可以用“或”连接起来。

    O_RDONLY 只读
    O_WRONLY 只写
    O_RDWR 可读可写
    O_CREAT 文件不存在,就创建新文件
    O_TRUNC 如果文件存在,就截断它
    O_APPEND 写操作前设置文件位置到结尾处
    mode参数指定了新文件的访问权限位
    

    image

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

    1.参数解析:

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

    10.4 读和写文件

    -读 read

    #include <unistd.h>
    
    ssize_t read(int fd, void *buf, size_t n);//返回有符号值
    
    成功则返回读的字节数,EOF返回0,出错返回-1。返回值为有符号数。
    
    1. 参数解析:

      fd:文件描述符

      buf:存储器位置

      n:最多从当前文件位置拷贝n个字节到存储器位置buf

    -写 write

    #include <unistd.h>
    
    ssize_t write(int fd, void *buf, size_t n);
    
    成功则返回写的字节数,出错返回-1。返回值为有符号
    

    (2)参数解析:

    fd:文件描述符
    
    buf:存储器位置
    
    n:最多从存储器位置buf拷贝n个字节到当前文件位置
    

    PS:read和write在正常情况下返回值是实际传送的字节数量。

    #include "csapp.h"
    int main(void)
    {
    char c;
    while(read(STDIN_FILENO,&c,1)!=0)
    write(STDOUT_FILENO,&c,1);
    exit(0);
    }
    
    
    • 该程序使用read和write调用一次一个字节地从标准输入复制到标准输出。

    • 不足值

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

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

    10.5 用RIO包健壮地读写

    • RIO:I/O包,会自动为你处理不足值
    • RIO的无缓冲的输入输出函数
    #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);
    
    rio_readn成功则返回传送的字节数,EOF为0(一个不足值),出错为-1
    rio_writen成功则返回传送的字节数,出错为-1,没有不足值。
    
    
    1. 参数:

      fd:文件描述符

      usrbuf:存储器位置

      n:传送的字节数

    • read遇到EOF只能返回一个不足值,write不会返回不足值。
    • 被中断时函数会重启read或write
    • RIO的带缓冲的输入函数
    ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);
    ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
    
    • 可以高效的从文件中读取文本行和二进制数据。

    • 文本行就是一个由换行符结尾的ASCII码字符序列。换行符数字值为0x0a.rio_readlineb函数从内部读缓冲区拷贝一个文本行,当缓冲区为空时,会自动地调用read重新填满缓冲区。rio_readn带缓冲区的版本:rio_readnb。

    • rio_readlineb从rp读出一个文本行(包括换行符)并把它存到usrbuf,并用空字符结束这个文本行。最多读maxlen-1个字节,剩下一个给结尾处的空字符。

    • rio_readnb最多读n个字节。

    • 课本实例

    #include "csapp.h"
    int main(int argc,char **argv)
    {
    int n;
    rio_t rio;
    char buf[MAXLINE];
    rio_readinitb(&rio,STDIN_FILENO);
    while((n=rio_readlineb(&rio,buf,MAXLINE))!=0)
    rio_writen(STDOUT_FILENO,buf,n);
    }
    
    
    • rio_readinitb从内部读缓冲区复制一个文本行,当缓冲区变空使,会自动地调用read重新填满缓冲区。以上程序一次一行地从标准输入复制一个文本文件到标准输出。

    10.6读取文件元数据

    • 通过调用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的数据结构

    st_size成员包含了文件的字节数大小,st_mode成员则编码了文件访问许可位和文件类型。
    
    - st_mode成员的文件类型:
    
    S_ISREG(m) 普通文件
    S_ISDIR(m) 目录文件
    S_ISSOCK(m) 网络套接字
    • 课本实例——展示了如何使用宏和stat函数来读取和解释一个问价的
    #include "csapp.h"
    int main(int argc,char **argv)
    {
    struct stat stat;
    char *type,*readok;
    Stat(argv[1],&stat);
    if(S_ISREG(stat.st_mode))
      type = "regular";
    else if(S_ISDIR(stat.st_mode))
      type = "directory";
    else
      type = "other";
    if((stat.st_mode & S_IRUSR))
      readok = "yes";
    else
      readok = "no";
    printf("type:%s,read:%s
    ",type,readok);
    }
    

    10.7读取目录内容

    • 应用程序可以用readdir系列函数来读取目录内容
    #include<sys/types.h>
    #include<dirent.h>
    DIR *opendir(const char *name);
    返回:若成功,则为处理的指针;若出错,则为NULL
    
    • 函数opendir以路径名为参数,返回指向目录流的指针。
    #include<dirent.h>
    struct dirent *readdir(DIR *dirp);
    返回:若成功,则为指向下一个目录项的指针,若没有更多的目录项或出错,则为NULL
    
    • dirent指向流,每个目录项都是一个结构

    • 函数closedir关闭流并释放其所有的资源。
    #include<dirent.h>
    int closedir(DIR *dirp);
    返回:成功为0,错误为-1
    
    

    10.8 共享文件

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

      • 描述符表:每个打开的描述符表项指向文件表中的一个表项。

      • 文件表:打开的文件的集合是由一张文件表表示的,所有的进程共享这张表。包括文件位置、引用计数(当前指向该表项的描述符表项数),指向v-node表的指针。

      • v-node表:包含stat结构中大多数信息。

    • 打开文件的内核数据结构:

    image

    • 共享了同一个磁盘文件:

    image

    • 子父进程共享文件
      子进程有一个父进程描述表符副本,所以他们共享打开文件的集合。注意,在内核删除相应文件表表项之前,子父进程必须都关闭他们的描述符。
      image

    练习

    • 10.1下面程序的输出是什么?
    #include "csapp.h"
    int main()
    {
    int fd1,fd2;
    fd1=open("foo.txt",O_RDONLY,0);
    close(fd1);
    fd2=open("baz.txt",O_RDONLY,0);
    printf("fd2=%d
    ",fd2);
    exit(0);
    }
    
    
    • 结果为:Unix进程生命周期开始时,打开的描述符赋给了stdin(描述符0)、stdout((描述符1)和stderr(描述符2)。open函数总是返回最低的未打开的描述符,所以第一次调用open会返回描述符3,调用close函数会释放描述符3。最后对open的调用会返回描述符3,因此程序的翰出是“fd2=3”。当文件不存在是,输出“fd2=-1”

    • 10.2 假设磁盘文件foobar.txt由6个ASCII码字符“foobar"组成,那么下列程序的输出是什么?
    #include "csapp.h"
    int main()
    {
    int fd1,fd2;
    char c;
    fd1=open("foobar.txt",O_RDONLY,0);
    fd2=open("foobar.txt",O_RDONLY,0);
    read(fd1,&c,1);
    read(fd2,&c,1);
    printf("c=%c
    ",c);
    exit(0);
    }
    
    • fd2读操作读取foobar.txt的第一个字节

    • 10.3 就像前面那样,假设磁盘文件foobar.txt由6个ASCII码字符“foobar"组成,那么下列程序的输出是什么?
    #include "csapp.h"
    int main()
    {
    int fd;
    char c;
    fd = open("foobar.txt",O_RDONLY,0);
    if(fork()==0)
    {
    read(fd,&c,1);
    exit(0);
    }
    wait(NULL);
    read(fd,&c,1);
    printf("c=%c
    ",c);
    exit(0);
    }
    
    • 描述符fd在父子进程中都指向同一个打开文件表表项,当子进程读取文件的第一个字节时,文件位置加1。因此,父进程会读取第二个字节,也就是o

    • 10.4 如何用dup2将标准输入重定向到描述符5?
    • dup2(5,0)
    • 10.5 假设磁盘文件foobar.txt由6个ASCII码字符“foobar"组成,那么下列程序的输出是什么?
    #include "csapp.h"
    int main()
    {
    int fd1,fd2;
    char c;
    fd1=open("foobar.txt",O_RDONLY,0);
    fd2=open("foobar.txt",O_RDONLY,0);
    read(fd2,&c,1);
    dup2(fd2,fd1);
    read(fd1,&c,1);
    printf("c=%c
    ",c);
    exit(0);
    }
    
    
    • 将fdl重定向到了fd2,输出实际上是c=o

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

    • 问题1:
    • 问题1解决方案:

    代码调试中的问题和解决过程

    • 问题1:在起初在编译时用gcc xx.c -o xx出现错误
    • 问题1解决方案:后来发现只要加一个-lpthread就行了,用命令gcc xx.c -o xx -lpthread

    上周考试错题总结

    • Y86-64中(ABE)指令没有访存操作.

    A .
    rrmovl

    B .
    irmovq

    C .
    rmmovq

    D .
    pushq

    E .
    jXX

    F .
    ret
    解析:jXX无访存操作

    • 16
      ( 多选题 | 1 分)
      有关磁盘操作,说法正确的是(ACD)

    A .
    对磁盘扇区的访问时间包括三个部分中,传送时间最小。

    B .
    磁盘以字节为单位读写数据

    C .
    磁盘以扇区为单位读写数据

    D .
    读写头总处于同一柱面

    • 有关RAM的说法,正确的是(ACDEG)

    A .
    SRAM和DRAM掉电后均无法保存里面的内容。

    B .
    DRAM将一个bit存在一个双稳态的存储单元中

    C .
    一般来说,SRAM比DRAM快

    D .
    SRAM常用来作高速缓存

    E .
    DRAM将每一个bit存储为对一个电容充电

    F .
    SRAM需要不断刷新

    G .
    DRAM被组织为二维数组而不是线性数组

    解析:静态RAM(SRAM)比动态RAM(DRAM)更快。

    代码托管

    结对及互评

    本周结对学习情况

    • 20155326
      • 结对照片

      • 结对学习内容

        • 第十章内容

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

    感觉I/O这块的内容一直都是重点而且无处不在,但是自己一直在这一块的学习上感觉存在不足,借这次机会正好再次认真学习了一遍。

    学习进度条

    代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
    目标 5000行 30篇 200小时
    第一周 5/5 1/1 15/15
    第二周 1/2 23/38
    第三周 206/327 1/3 28/66
    第四周 206/327 1/4 10/77
    第五周 285/568 1/5 20/97 主要学习了汇编及反汇编的相关知识
    第六周 160/683 3/8 20/107
    第七周 / 2/10 20/127 第四章学习内容和第二次实验
    第八周 2/12 22/149 第十一章、第十二章
    第九周 408/ 2582 3/15 21/170 第六章内容、第三次实验、课后pwd的实现
    第十一周 174 / 3035 3/18 20/200 第九章内容、实验四
    第十三周 741/3776 2/22 20/220 第十二章再学习
    第十四周 87/3863 1/23 20/240 第十章再学习

    尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
    耗时估计的公式
    :Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。

    参考:软件工程软件的估计为什么这么难软件工程 估计方法

    参考资料

  • 相关阅读:
    iostream迭代器操作"txt文本文件"无法写入的思考
    Qt 相对路径 绝对路径
    "lambda"和“bind”的初步思考
    "partition"和“stable_partition”的思考
    "accumulate"的思考
    顺序容器“inset”的思考
    C++重载函数 const形参 引用指针 const_cast
    C++ 可变参数的函数
    JDK8流式处理常用例子
    JDK8时间新API
  • 原文地址:https://www.cnblogs.com/ljq1997/p/8098558.html
Copyright © 2020-2023  润新知