信息安全系统设计基础第九周学习总结

时间:2022-09-05 11:07:43

系统级I/O

为什么要学习Unix I/O

 1.了解Unix I/O将帮助你理解其他的系统概念
2.有时候除了用Unix I/O别无选择

10.1 Unix I/O

一个Unix文件就是一个m字节的序列,所有的I/O设备都被模型化为文件,所有的输入输出操作都被当做对文件的读写来执行

1 打开文件:

1)、描述符:一个应用程序通过要求内核来打开相应的文件来宣告他想访问一个I/O设备,内核返回的一个小的非负整数

  • 作用:在后续对此文件的所有操作中标示这个文件,应用程序只需记住这个描述符。

2)、每个进程开始时都有三个打开的文件:标准输入,标准输出(描述符为1)和标准错误(描述符为2)

2 改变当前的文件位置:

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

读写文件:

1)、读操作:从文件拷贝n>0个字节到存储器。从文件位置k开始,将k增加到k+n

  • 对于给定的m字节的文件,若k>=m时会出发一个EOF条件

2)、写操作:从存储器拷贝n>0个字节到文件

关闭文件:

1)、当应用完成访问文件之后,通知内核关闭这个文件
2)、内核释放文件打开时创建的数据结构,并将描述符恢复

10.2 打开和关闭文件:

进程是通过调用open函数来打开或创建文件的

int open(char *filename,int flags,mode_t maode);
open函数将filename转换成一个文件描述符,并且返回描述符数字

  • flags参数:

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

    O_CREAT:如果文件不存在就创建一个新的截断的空文件
    O_TRUNC:如果文件已经存在就截断他
    O_AAPEND:在每次操作前设到文件的结尾处

  • 如何以读的方式打开一已存在的文件:

    fd = Open("foo.txt",O_RDONLY,0);

  • 如何打开一个一存在文件并在后面加数据:

    fd = Open("foo.txt",O_WRONLY|O_APPEND,0);

mode定义了一个新文件的访问权限位

进程通过调用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);

传送字节不应用程序要求的少,出现不足值错误的情况:
1 读时遇到EOF
2 从终端读文本行
3 读和写网络套接字

10.4 用RIO包健壮的读写

RIO包提供两种不同的函数:

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

直接在存储器和文件之间传送数据,对二进制数据和网络之间的传送尤其有用

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

10.4.2 带缓冲的输入函数:

一个文本行就是由一个换行符结尾的ASCII码字符序列。高效的从文件中读取文本行和二进制数据
包装函数:从一个内部读缓冲区拷贝一个文本行,当缓冲区变空时会自动调用read函数填满缓冲区
信息安全系统设计基础第九周学习总结
读程序的核心是rio_read函数

10.5 读取文件元数据

元数据:应用程序能够调用stat和fstat函数,检索到关于文件的信息元数据

参数:

stat函数以文件名作为输入
fstat函数以文件描述符作为输入
stat数据结构中的重要成员:st_mode,st_size
st_size成员包含了文件的字节数大小
st_mode成员编码了文件访问许可位和文件类型

文件类型:

  • 普通文件:二进制或文本数据,宏指令:S_ISREG()
  • 目录文件:包含其他文件的信息,宏指令:S_ISDIR()
  • 套接字:通过网络和其他进程通信的文件,宏指令:S_ISSOCK()
  • Unix提供的宏指令根据st_mode成员来确定文件的类型

10.6 共享文件

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

  • 描述符表:每个进程有独立的描述符表,表项由进程打开的文件描述符来索引的
  • 文件表:由文件位置、引用计数以及一个指向v-node表中对应表项的指针组成
    所有的文件共享一张表,关闭一个描述符会减少相应的引用计数。
  • v-node表:同文件表。灭个表项包含stat结构中的信息,包括st_mode和st_size成员

关键思想是:每个描述符都有自己的文件位置,所以对不同描述符的读操作可以从文件的不同位置获取数据
父子进程重要的结果:在内核删除了相应文件表表项之前,父子进程都必须关闭他们的描述符

10.7 I/O重定向

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

工作方式:使用dup2函数

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

10.8 标准I/O

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

incldue
extern FILE stdin;
extern FILE
stdout;
extern FILE *stderr;

10.10 小结

1、Unix提供了少量的系统级函数,包括:

  • 打开、关闭、读写文件、提取文件元数据、执行I/O重定向
    2、读写程序出现不足值,应调用RIO包发福进行读写操作,自动处理不足值
    3、标准I/O库和Unix I/O库:
  • 标准I/O库是基于Unix I/O库产生的,比Unix I/O库简单
  • Unix I/O库兼容限制小,比标准I/O库更适用于网络程序

错误处理

A.1 Unix系统中的错误处理

  • 系统级函数调用使用三种不同风格的返回错误:Unix风格、posix风格和DNS风格

1.Unix风格的错误处理

早期开发的函数返回值既包括错误代码也包括有用的结果
错误代码通常具有的格式:
信息安全系统设计基础第九周学习总结

2.POSIX风格的错误

只用返回值来表示成功或失败,任何有用的结果都返回在通过引用传递进来的函数参数中
错误代码通常具有的格式:
信息安全系统设计基础第九周学习总结

3.

在失败是返回NULL指针,并设置全局变量h_errno
错误代码通常具有的格式:
信息安全系统设计基础第九周学习总结

4.小结

包容不同错误处理风的错误报告函数

include "csapp.h"
void unix_error(char msg);
void posix_error(int code,char
msg);
void dns_error(char msg);
void app_error(char
msg);

A.2 错误处理包装函数

1.Unix风格的错误处理包装函数

返回一个错误时,包装函数打印一条消息后退出;否则向调用者返回一个PID
kill函数的包装函数
信息安全系统设计基础第九周学习总结

2.POSIX风格的错误处理包装函数

错误返回码中不会包含有用的结果,所以成功时包装函数返回void
pthread_detach函数的包装函数
信息安全系统设计基础第九周学习总结

3.DNS风格的错误的包装函数

gethostbyname函数的包装函数
信息安全系统设计基础第九周学习总结