教材学习内容总结
Unix I/O
- Unix文件就是一个m字节的序列:b0,b1,b2….bm-1。将所有的I/O设备都被虚拟化为文件。所有的输入输出都是在当成相对应的文件的读写。将设备映射为文件。
打开和关闭文件
- 函数
int open(char *filename,int flags,mode_t mode)
- 参数解释:
1、返回值:类型为int型,将一个filename转换为一个文件描述符,返回一个描述符数字,总是在进程中当前没有打开的最小描述符。如果出错,返回值为-1.
2、filename:文件名
3、flags:指明进程打算如何访问这个文件,可以取的值见下:
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:可读可写
O_CREAT:文件不存在,就创建新文件
O_TRUNC:如果文件存在,就截断它
O_APPEND:写操作前设置文件位置到结尾处
这些值可以用“或”连接起来。
4、mode:指定了新文件的访问权限位
读和写文件
ssize_t read(int fd, void *buf,size_t n)
read函数从描述符为fd的当前文件位置拷贝最多n个字节到存储器位置buf。返回值-1表示一个错误,而返回值0表示EOF。否则,返回值表示的是实际传送的字节数量。ssize_t write(int fd,void *buf,size_t n)
write函数从存储器位置buf拷贝至多n个字节到描述符fd的当前文件位置。返回值要么为-1,要么为写入的字节数目
用RIO包健壮地读写
1、无缓冲的输入输出函数(直接在存储器和文件之间传送数据,没有应用级缓冲,它们对将二进制数据读写到网络和从网络读写二进制数据尤其有用),对同一个描述符,可以任意交错地调用rio_readn和rio_writen;
2、带缓冲的输入函数,对同一个描述符,可以任意交错地调用rio_readnb和rio_readineb。
读取文件元数据
- 应用程序能够通过调用stat和fstat函数检索到关于文件的信息(有时也称为文件的元数据),若成功,返回0,若出错则为-1.
- stat以一个文件名为输入,并且填充buf结构体。fstat函数只不过是以文件描述符而不是文件名作为输入。
- stat结构体中,st_size成员包含了文件的字节大小,st_mode为文件访问许可位。UNIX提供的宏指令根据st_mode成员来确定文件的类型:S_ISREG(),这是一个普通文件,S_ISDIR(),这是一个目录文件;S_ISSOCK()这是一个网络套接字。
共享文件
内核用三个相关的数据结构来表示打开的文件:描述符表,文件表,v-node表。
个相关的数据结构表示打开的文件:
-
描述符表:每个打开的描述符表项指向文件表中的一个表项。
-
文件表:打开的文件的集合是由一张文件表表示的,所有的进程共享这张表。包括文件位置、引用计数(当前指向该表项的描述符表项数),指向v-node表的指针。
-
v-node表:包含stat结构中大多数信息。
I/O重定向
通过dup2函数,对描述符表表项进行拷贝覆盖,实现重定向。
错误处理
系统级函数调用,3种不同风格的返回错误:Unix风格、 Posix风格、 DNS风格。
遇到的问题及解决方法
1、在编译时系统没有“csapp.h”文件,在网上查到资料应该在linux下自己写入“csapp.h”,fedora的,要放到 /usr/include的文件夹里面。而ubuntu下是/usr/lib。在保存文件时出现了下面的问题:
使用wq!强制保存也没有用,后来查阅资料可以用:sudo vim 文件名打开文件然后再编译就可以啦。
2、在编译文件时,Open函数和Read函数未定义,我以为是csapp.h头文件的问题,但是解决了头文件后,还是出现函数未定义,后来我尝试着把两个函数的名字统一改成小写的,编译成功。
下图是习题10_2成功运行结果:
本周代码托管
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 3500行 | 30篇 | 400小时 | |
第一周 | 40/40 | 1/1 | 20/20 | |
第二周 | 30/70 | 1/2 | 30/50 | |
第三周 | 21/91 | 1/3 | 28/78 | |
第五周 | 131/222 | 1/4 | 20/98 | |
第六周 | 32/254 | 1/5 | 21/119 | |
第七周 | 200/454 | 1/5 | 21/119 | |
第八周 | 0/454 | 1/6 | 10/129 | |
第九周 | 84/538 | 1/7 | 15/144 |