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

    10系统级I/O

    10.1 Unix I/O

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

    打开文件:

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

    文件描述符:

    • 标准输入——0(STDIN_FILENO)
    • 标准输出——1(STDOUT_FILENO)

    标准错误——2(STDERR_FILENO)

    改变当前的文件位置

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

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

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

    读写文件

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

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

    关闭文件

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

    10.2打开和关闭文件

    1.open函数

    (1)函数定义:

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

     

    intopen(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>

     

    intclose(intfd);

    (2)参数解析:

    • 返回值:成功返回0,出错返回-1
    • fd:即文件的描述符。

    10.3读和写文件

    1. read

    (1)函数原型:

    #include<unistd.h>

     

    ssize_tread(intfd, void *buf, size_t n);

    (2)参数解析:

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

    2. write

    (1)函数原型:

    #include<unistd.h>

     

    ssize_twrite(intfd, void *buf, size_t n);

    (2)参数解析:

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

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

    4.不足值

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

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

    10.4 RIO包健壮的读写

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

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

    rio_readn函数和rio_writen定义:

    #include "csapp.h"

     

    ssize_trio_readn(intfd, void *usrbuf, size_t n);

    ssize_trio_writen(intfd, void *usrbuf, size_t n);

    参数:

    • usrbuf:存储器位置
    • n:传送的字节数

    返回值:

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

    rio_writen成功则返回传送的字节数,出错为-1,没有不足值。

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

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

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

    rio_readnb函数

    ssize_trio_readnb(rio_t *rp, void *usrbuf, size_tn)

    {

    size_tnleft = n;

    ssize_tnread;

    char *bufp = usrbuf;

     

    while (nleft> 0) {

            if ((nread = rio_read(rp, bufp, nleft)) < 0) {

            if (errno == EINTR)

                   nread = 0;      /* 调用read填充 */

            else

                   return -1;      /* 错误,返回-1 */

            }

            elseif (nread == 0)

            break;              /* EOF */

            nleft -= nread;

            bufp += nread;

        }

    return (n - nleft);         /* 返回成功传送的字节数*/

    }

    rio_readlineb函数

    ssize_trio_readlineb(rio_t *rp, void *usrbuf, size_tmaxlen)

    {

    intn, rc;

    char c, *bufp = usrbuf;

     

    for (n = 1; n<maxlen; n++) { //最多是maxlen-1个

            if ((rc = rio_read(rp, &c, 1)) == 1) {

                *bufp++ = c;

            if (c == ' ')//找到换行符,就退出

                   break;

            } elseif (rc == 0) {

            if (n == 1)

                   return 0; /* EOF,并且没有读到数据 */

            else

                   break;    /* EOF,有数据,出现不足值 */

            } else

            return -1;     /* 错误,返回-1 */

        }

        *bufp = 0;

    returnn;//返回成功传送的字节数

    }

    10.5读取文件元数据

    元数据即文件信息,需要用到的函数是stat和fstat。定义如下:

    #include<unistd.h>

    #include<sys/stat.h>

     

    intstat(constchar *filename, struct stat *buf);

    intfstat(intfd,struct stat *buf);

     

    返回值:成功为0,错误为-1

    参数:

    stat需要输入文件名,而fstat需要输入的是文件描述符。

    关于stat数据结构如下图:

    • st_size:包含文件的字节数大小

    st_mode:包编码文件访问许可位和文件类型。许可位在第一节提到了,Unix文件类型如下,并有对应的宏指令,含义均为“是xx吗”,这些宏在sys/stat.h中定义:

    • 普通文件    二进制或文本文件(对内核没差) S_ISREG()
    • 目录文件    关于其他文件的信息     S_ISDIR()

    套接字      通过网络与其他进程通信的文件   S_ISSOCK()

    10.6共享文件

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

    • 描述符表
    • 文件表:打开文件的集合是由一张文件表来表示的。
    • v-node表

    每个描述符都有它自己的文件位置,所以对不同描述符的读操作可以从文件的不同位置获取数据。

    子进程继承父进程的打开文件:

    参考资料

    1.2035202闫佳歆与20135302魏静静

    2.《深入理解计算机系统》

    3.百度百科知识

    stdio.h   标准输入输出

    stdlib.h  C标准函数库

    unistd.h  Unix类系统定义符号常量

    fcntl.h   定义了很多宏和open,fcntl函数原型

    sys/types.h         基本系统数据类型

    dirent.h  unix类目录操作的头文件,包含了许多UNIX系统服务的函数原型,例如opendir函数、readdir函数。

    termios.h 在Posix规范中定义的标准接口

     

    学习总结 遇到的问题:

    预计学习时间:6h实际学习时间:10h

    在编译代码时,与小组同学们遇到了一样的问题,发现不能运行csapp这个头文件,推理这个应该是自己编的。发现有两个解决办法,一个是老师之前在班群里的代码,一个是同学修改了头文件,是函数正常输出。她的博客写了解决方法(20135302)。另外,本章内容少,但是有些代码还是不太懂,有时候要靠一句句地百度理解。虽然老师上课,有给我们介绍一点知识,但是本章的学习还是要靠自学,研究函数的返回值与参数等,学了一个函数,掌握其方法,其他就可以举一反三啦。

    实践代码:下面四图各为老师给的代码运行的结果。cp1,cp2,who1,who2

     

     

     

     

     

     
  • 相关阅读:
    项目需求分析
    对软件开发的感想
    趣拼图最后完成及总结
    UML用例图
    数据流图和数据流程图
    第三代迭代目标
    Scrum的三种角色划分及小组成员分工
    WBS Model
    团队开发—百科全书软件项目
    开发流程
  • 原文地址:https://www.cnblogs.com/zhengwei0712/p/4948401.html
Copyright © 2011-2022 走看看