signed

QiShunwang

“诚信为本、客户至上”

深入计算机系统基础——系统级I/O技术日志

2020/12/28 3:58:08   来源:

深入计算机系统基础——系统级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,代码分析纯原创,花了一定时间用心去理解了“读和写文件”的部分。码字不易,如果有不正确的地方希望指出包涵。