深入计算机系统基础——系统级I/O技术日志
- Uinx I/O
- 文件
- 打开和关闭文件
- 读和写文件
- 代码举例分析(代码部分来自于第十章课堂PPT)
- 总结
Uinx I/O
概念:所有的I/O设备都被模型化为文件,而所有的输人作对相应文件的读和写来执行。这种将设备优雅地映射为文件的方式,允许Linux内核出一个简单、低级的应用接口,称为Unix 1/O。(来源于《深入计算机系统基础 第三版》)
- 打开文件即打开指令中要求打开的文件。
- Linux shell创建的每一个进程开始时都有三个打开的文件:标准输入(描述符为0),标准输出(描述符为1),标准错误(描述符为2)。
- 改变当前文件位置。
- 读写文件。
- 关闭文件。
文件
- 普通文件
- 目录
- 套接字
打开和关闭文件
-
调用open函数打开文件
- O-RDONLY:只读 - O-WRONLY:只写 - O-RDWR:可读可写 - O-CREAT:如果文件不存在,就创建一个截断的空文件 - O-TRUNC:如果文件存在,就截断 - O-APPEND:在每次写操作前,设置文件位置到结尾处
-
调用close函数可以关闭一个打开的文件
读和写文件
分别调用read和write函数来执行输入和输出
代码举例分析
观察以下代码:
what would this program point for file containing “abcde”
#include "csapp.h"
int main(int argc, char *argv[])
{
int fd1, fd2, fd3;
char c1, c2, c3;
char *fname = argv[1];
fd1 = Open(fname, O_RDONLY, 0);
fd2 = Open(fname, O_RDONLY, 0);
fd3 = Open(fname, O_RDONLY, 0);
dup2(fd2, fd3);
Read(fd1, &c1, 1);
Read(fd2, &c2, 1);
Read(fd3, &c3, 1);
printf("c1 = %c, c2 = %c, c3 = %c\n", c1, c2, c3);
Close(fd1);
Close(fd2);
Close(fd3);
return 0;
}
输出结果
/*
$ gcc ffiles1.c csapp.h csapp.c -lpthread -o ffiles1
$ ./ffiles1 abcde.txtc1 = a, c2 = a, c3 = b
*/
原因分析:
最初fd1,fd2,fd3都在不同的进程中打开fname文件,dup2函数的作用是可以复制一个函数描述符,等价于close(oldfd);fcntl(oldfd, F_DUPFD, newfd);。dup2(fd2, fd3); 的作用即为使fd2的指令赋给fd3,即fd3原来的指令不再起作用,而是跟在fd2的指令之后再次执行fd2指令。因此fd1指令执行的c1=a;fd2重新打开一个新的文件,因此读取的第一个字符为c2=a;由于调用dup2函数的原因,fd3跟在fd2后执行,由于第一个字符a已经被fd2指令读取,因此fd3读取的字符c3=b。
总结
此次的技术日志的概念部分有来源于《深入计算机系统基础 第三版》以及自己对系统I/O的理解。
代码分析部分的代码来源于课上PPT,代码分析纯原创,花了一定时间用心去理解了“读和写文件”的部分。码字不易,如果有不正确的地方希望指出包涵。