理解计算机系统_文件管理_系统级I/O(一)

前言
       

        以<深入理解计算机系统>(以下称“本书”)内容为基础,对程序的整个过程进行梳理。本书内容对整个计算机系统做了系统性导引,每部分内容都是单独的一门课.学习深度根据自己需要来定

引入

        底层部分内容说难那也是挺难,但难度不是在理解上,而是并没有什么代码可以写.各种概念的实现都是半猜半记,本书没有提供对应的工具去开发(有是有但笔者不知道)

        如前所述,数据是程序中最重要的部分(对软件程序员来讲),对数据的理解也是学习编程最好的切入点."一切都是数据,一切逻辑的实现都需要用数据表达".对这个概念应该有所觉悟.

文件基础认识

        数据回顾

        硬件层面:数据有地址和值两部分---地址用于数据传递,值表示数据含义.值也可以是地址,当值是地址的时候,需要继续向下解析.

        软件层面:数据有类型限制---所有数据都归于一种类型(在面向对象中还可属于其继承的类型).数据由指针访问(基础数据类型由变量访问,但变量本质上仍是地址)

         认识I/O

        本书原话:输入/输出(I/O)是在主存和外部设备(例如磁盘驱动器、终端和网络)之间复制数据的过程.输入操作是从I/O设备复制数据到主存,而输出操作是从主存复制数据到I/O设备.---黑体字是原话.

        ---I/O即数据的传递

        为什么需要理解Unix I/O

        1>所有语言的运行时系统都提供执行I/O的较高级别工具.例如,C提供标准I/O库,包含printf和scanf这样执行带缓冲区的I/O函数.C++语言用他的重载运算符<<和>>提供输入输出功能.为什么要学习Unix I/O呢?我们经常遇到I/O和其他系统概念之间的循环依赖.例如进程和 I/O密不可分

        2>有时候除了Unix I/O别无选择.

        例如:标准 I/O没有提供读取文件元数据的方式,例如文件大小或文件创建时间.

                另外 I/O库用来网络编程非常冒险

        ----上述黑体字是除了标准I/O外需要理解 Unix I/O的原因

        文件的本质是什么

        本书原话:一个Linux文件就是一个m个字节的序列:B0,B1,....Bm-1.所有的I/O设备(例如网络,磁盘和终端)都被模型化为文件,而所有的输入和输出都被当作对相应文件的读和写来执行.---黑体字是原话

        1)文件是一个字节序列

        2)文件是对硬件设备的抽象

        本章中最重要的点在这里.硬件被抽象为文件.他的含义是:文件和硬件寄存器之间存在映射关系,当然文件的具体内容是什么,怎样排布,是由驱动怎么写决定的. 

        举个例子:假设有一个硬件A,有传感器和灯,传感器由8个字节的寄存器采集数据,8个字节的寄存器控制64个灯.那么可以用文件的读写方式建立起两个函数来和硬件A通信.

        该文件有16个字节,前8个字节是传感器采集到的数据,后8个字节是用来控制64个灯的.尝试写出如下代码:

//伪代码
enum class Status{status_1,status_2,....status_n}  //声明状态的枚举

Status showStatus(){         //采集状态的函数
    int fd=Open("路径");     //打开文件所在路径的函数Open在后面有
    long buf;                //声明8字节空间,为接收传感器的8个字节做准备
    read(fd,&buf,8);         //读取8字节到buf中,read函数后面有
    if (buf==1)              //采集到的数据1等于1
        return status_1;     //枚举表示状态1
    else if(buf==2)          //采集到的数据2等于2
        return status_2;     //枚举表示状态2  
    ...                      //其他

}

void light(Sometype st){     //点亮某些个灯的函数
    int fd=Open("路径");     //打开文件所在路径的函数Open在后面有
    if (情况1)               //情况1下点亮前面8个灯,一个字节
        char n=255;          //内存空间中申请一个n,设为255,8个1.
        seek(8);             //显式设置文件当前位置为8,见本书P623(代码不保证正确)
        write(fd,&n,1);      //把n的地址传给write函数,1个字节,那么这8个1写给文件把灯点亮
    else(情况2)
        其他...
}

        :这段代码实在抽象,将就看一下.枚举是定义在什么地方的?假设标准中有

              而且笔者做了一个假设:文件只映射寄存器,是否有函数未知.因为在平常印象中,文件有数据还有函数.

         而笔者想表达的是:showStatus和light这类函数的集合,实际上将被汇集成为标准.参考笔者另一篇程序构建---标准是什么-优快云博客.那么这就是非常好的地方:程序员是面向标准开始编程,文件隐藏了硬件部分的实现细节.

        文件所在的层次大致如下图所示:

        站在这个角度来看,文件和程序员关系并不大.文件的读写操作由系统内核封装给了标准,而程序员照着标准编程.当遇到问题时,再来看实现部分.

文件的执行方式        

        1>打开文件 

          标准I/O库调用open打开文件后,返回一个非负整数,叫做描述符.但他并不是指针(有点奇怪)

        2>三个标准文件

           每个进程开始时默认三个打开文件,标准输入(描述符0),标准输出(描述符1),标准错误(描述符2).推导进程想打开其他文件的时候,描述符从3开始.    

        3>改变当前的文件位置

              描述符不是文件指针,内核保持一个文件位置k,初始为0,从文件开始的字节偏移量.应用程序能通过执行seek操作,显式设置当前文件的位置k.  

        4>读写文件

                读文件操作从文件当前位置复制n>0个字节到内存,写文件是从当前位置k开始,都更新k

        5>关闭文件

                内核释放资源,文件使用的描述符恢复可用状态.

简单来说,文件打开,读写和关闭的操作流程.注意文件的描述符不是指针,由seek函数确定文件位置.

文件分类

         每个Linux文件都有一个类型来表明他在系统的角色

        1>普通文件

        特点:包含任意数据

        分类:文本文件和二进制文件.

        二进制文件就是0和1组成的文件.

        文本文件只含ASCII码或者Unicode字符的普通文件,文本文件是文本行序列,每个文本行是一个字符序列.文本行以新行符(换行符)'\n'结尾.

        2>目录

        包含一组链接的文件.目录下面包含文件或者其他目录

        重点是目录的设计,从类型设计上来看,他是由一种"递归"的思想设计出的数据类型.如果用C++表示,大致如下:

struct Directory{
    vector<Directory> next_layers;
}

        用口头语言来表达:"我"包含的数据是若干个和"我"相同的数据---可能有多个,可能没有(最后一层).可能是笔者孤陋寡闻,从没见过哪本书提到过这种设计,所以可以算是一点小小心得做奉献.

        他和链表有点像但又不是链表,链表里没有表明下一层的"我"的个数,所以只被作为两个数据之间的链接.当然按照动态数组的思路,加上一个数量的属性也是同样的效果.

        准确表达,他的类型应该是这样的:

struct Directory{
    vector<File> files;
    vector<Directory> next_layers;
}

        修正:笔者之前在数据类设计_图片类设计之7_矩阵图形类设计更新_实战之页面简单设计(前端架构)-优快云博客提到的矩阵图形类设计中采用了"散列算法"是不准确的.散列表和这个不一样,这是由递归思想设计出来的层级数据结构,抱歉.

        此外,在设计模式中,有一种职责链模式,也采用了递归思想.

        3>套接字

                用来与另一个进程进行跨网络通信的文件

目录层次

        绝对路径

                以斜杠开始,表示根节点开始的路径.

        相对路径

                以当前工作目录开始,以1个点(.)和/表示访问当前目录中的文件或目录.

                                                  以2个点(..)和/表示访问上一级目录开始访问

小结

        文件初探

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重庆彭枫

你的鼓励是我创作的动力,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值