9.文件基本操作
第四章 文件管理
9.文件基本操作






“打开文件和关闭文件”与平常鼠标双击打开文件和点击“X”关闭文件是有所不同的。
操作系统在处理open系统调用时主要做了以下两件事情,①根据我们提供的文件存放路径在外存当中找到这个目录对应的目录表,另外不同的用户对文件的操作权限是不一样的,有的用户可能只可以读这个文件,而有的用户既可以读文件也可以写文件,而这些用户对文件的访问权限信息(访问控制列表ACL)其实也是记录在目录项当中的,所以可以根据目录项来检查此时用户请求的这个操作到底是否合法,如果用户没有这种操作权限的话就可以拒绝用户打开文件;而如果用户有这种操作权限的话,那么接下来操作系统会把这个文件对应的目录项复制到内存中的“打开文件表”中,也就是说在用户打开了一个文件之后,这个文件相关的信息就已经放到内存当中了,之后用户想要再操作这个文件只需要根据这个“打开文件表”的编号就可以找到自己想要操作的这个文件的一切信息,这样的话就不需要每次查文件的时候都重新访问目录了,因此把目录项复制到打开文件表当中是可以大幅度的提升文件访问的速度的。
需要注意的是有两种打开文件表,一种是系统的打开文件表(整个系统只有一张),这个打开文件表中会记录所有的正在被其他进程使用的文件的一些信息。另外每个进程也会有自己的打开文件表,这张表中记录了自己的这个进程此时已经打开的文件是哪些,在进程的打开文件表中会有一个系统表的索引号,比如“test.txt”这个文件在系统打开文件表中是编号k这个表项,那么进程打开文件表会记录下这个编号k;同样的如果另一个进程B也打开了“test.txt”这个文件那它同样也会指向系统的打开文件表。在系统的打开文件表中有一个字段“打开计数器”,用来记录这个文件此时已经被几个进程打开了,此时如果有两个进程打开了这个文件的话,那这个打开计数器就应该修改为2。“打开计数器”这个字段是系统打开文件表中所特有的一个字段。
在整个系统当中设置一个打开文件表的总表(即系统打开文件表)是比较方便实现某一些文件管理功能的。比如说在使用Windows操作系统的时候如果我们要尝试删除某一个txt文件,那此时如果这个txt文件已经被某个记事本进程打开了,那么系统是会提示我们暂时无法删除该文件,其实系统在背后做的事情就是当我们选择删除文件的时候它首先来检查这个文件是否已经被某个进程打开了,也就是查询了系统当中的打开文件表,如果此时这个文件正在被某个进程使用的话,那么这个文件的数据显然是暂时不能删除的,所以如果我们在系统当中设置了一个系统打开文件表这样的总表,那么对于一些文件管理的功能是很方便实现的。另外,在进程的打开文件表当中会有一个字段“读写指针”,记录了这个进程对文件进行读写操作此时进行到了什么位置。在进程的打开文件表中还需要标明这个进程对文件的访问权限。比如说进程A在打开test.txt这个文件的时候只是声明了自己只会对test.txt这个文件进行“只读”操作,那么如果这个进程在之后尝试对这个文件进行“写操作”,那操作系统会检查它之前申请的访问的类型,由于之前它只是声明了“只读”,所以这个写操作应该拒绝。在进程打开文件表中比较特殊的是“读写指针”,和“访问权限”这两个字段,不同的进程对一个文件进行读写操作进行到的位置是不一样的,所以不同进程的读写指针也是应该不一样;另外不同的进程在打开一个文件的时候所申请的这种访问类型也是不一样的,因此访问权限这个字段也应该放在进程的打开文件表中。当然除了这里列出的字段之外,在进程的打开文件表中还会有其他的一些文件的信息,这里没有全部列举。

用户使用完一个文件,要“关闭文件”:
当这个进程选择关闭一个文件的时候那么可以把这个进程的打开文件表中这个文件对应的表项删除,相应的需要回收分配给这个文件内存缓冲区等等一系列的资源。另外需要对系统打开文件表中对应表项的打开计数器进行-1操作,由于此时这个打开计数器依然是>0的,所以说明此时这个文件还在被其中的某一些进程所使用,因此系统打开文件表中对应的表项暂时还不能删除,只有打开计数器为0的时候才需要删除系统打开文件表中的表项。

读文件、read系统调用:
在我们双击打开test.txt这个文本文档的时候在背后其实是调用了操作系统提供的read系统调用,也就是读文件的功能。通过之前的讲解可以知道,在对文件进行读写操作之前一定要先打开文件,所以其实在正式开始读文件的时候“记事本”这个进程的打开文件表当中已经有了这个文件对应的表项了,因此记事本这个进程在读文件的时候只需要指明自己要读的这个文件它对应的打开文件表中的编号到底是多少就可以了。这就是读文件的时候需要提供的第一个参数,就是要指明到底要读的是哪一个文件。第二个在读文件的时候还需要指明此时需要读入多少数据,另外还要指明这个读入的数据是存放在内存中的什么位置。这些参数的填充都是“记事本”这个进程在背后为我们完成的事情。
操作系统在处理read系统调用的时候会根据打开文件表中读写指针这个读指针所指向的外存地址那个地方读入用户指定的大小的这么多数据然后放入到用户指定的内存区域当中。

写文件和读文件是很类似的,在编辑完一个文本文档之后,我们可以点击文件保存,点击保存之后其实记事本这个应用程序在背后是帮我们调用了操作系统提供的写文件功能即write系统调用,这个系统调用的作用就是把这个文件在内存当中的数据再写回到外存,保存到外存当中。所以在进行write系统调用的时候我们也需要提供这样的几个参数,第一需要指明要写的是哪个文件,同样的这个进程只需要指明这个文件在打开文件表中的编号是多少,操作系统就知道要写的是哪个文件了。另外还需要指明这个写操作需要写回的数据大小到底是多少,另外还需要指明要写回外存的这些数据是放在内存当中的什么位置的。 操作系统根据write系统调用的参数,会从用户指定的内存区域中读出指定大小的数据然后写回“写指针”所指向的外存区域当中。

总结:
最重要的是打开文件,该操作会把目录项的信息复制到内存当中的打开文件表中,需要知道内存当中有两种打开文件表,一种是系统的打开文件表(整个系统只有一张),另外一种是进程打开文件表。系统的打开文件表中包含了所有的正在被使用的文件信息,而进程的打开文件表中只包含了这个进程本身打开了的那些文件信息。
需要注意的是在打开文件的时候并不会把文件的数据直接读入内存,只是把文件的目录项给复制到了内存的打开文件表当中。另外系统会把打开文件表当中的索引号返回给用户,之后用户就可以根据这个索引号来查询打开文件表然后直接操作自己的文件,而不用再每一次都查询目录,这个地方的索引号在有的教材上也称为“文件描述符”,这个术语在真题中出现过。所以“文件描述符”这个术语也需要注意一下,它指的其实就是进程的打开文件表中的编号。
另外需要注意在进程的打开文件表和系统的打开文件表中都会有一些各自特有的属性,比如每个进程都不一样的读写指针和访问权限,这些肯定需要放在进程的打开文件表中的,而一个文件总共被多少个进程打开了这个数据肯定是需要放在系统的打开文件表中。
比较容易和打开文件混淆的是读文件这个操作,只有读文件的时候才会把文件的数据真正的从外存读入内存。 而对文件进行读写操作的时候用户不需要再提供文件名,文件路径这些信息,只需要提供“文件描述符”也就是这个文件在打开文件表当中的索引号,操作系统就可以知道要读写的是哪个文件了。
相关文章:
9.文件基本操作
第四章 文件管理 9.文件基本操作 “打开文件和关闭文件”与平常鼠标双击打开文件和点击“X”关闭文件是有所不同的。 操作系统在处理open系统调用时主要做了以下两件事情,①根据我们提供的文件存放路径在外存当中找到这个目录对应的目录表&#x…...
【Java】Spring——Bean对象的作用域和生命周期
文章目录 前言一、引出Bean对象的作用域1.普通变量的作用域2.Bean对象的作用域 二、Bean对象的作用域1.Bean对象的6种作用域2.设置Bean对象的作用域 三、Bean对象的生命周期总结 前言 本人是一个普通程序猿!分享一点自己的见解,如果有错误的地方欢迎各位大佬莅临指导,如果你也…...
数字孪生助力智慧水务:科技创新赋能水资源保护
智慧水务中,数字孪生有着深远的作用,正引领着水资源管理和环境保护的创新变革。随着城市化和工业化的不断推进,水资源的可持续利用和管理愈发显得重要,而数字孪生技术为解决这一挑战提供了独特的解决方案。 数字孪生技术…...
css 实现文字横向循环滚动
实现效果 思路 ## 直接上代码,html部分 //我这里是用的uniapp <view class"weather_info_wrap"><view class"weather_info">当前多云,今晚8点转晴,明天有雨,温度32摄氏度。</view><view class&qu…...
VuePress 数学公式支持
前言 博主在为 VuePress1.0 博客添加数学公式支持过程中遇到如下问题 问题一 在配置诸如 markdown-it-texmath,markdown-it-katex,markdown-it-mathjax3 这些插件后遇到 Error: Dynamic require of "XXX" is not supported 问题二 配置插件 vuepress-plugin-ma…...
stm32控制蜂鸣器源代码(附带proteus线路图)
说明: 1 PB0输出0时,蜂鸣器发生; 2 蜂鸣器电阻值如果太大会导致电流太小,发不出声音; 3蜂鸣器额定电压需要设置得低一点,可以是2V,但不能高于3V,这更右上角的电阻值有关系&#x…...
selinux
一、selinux的说明 二、selinux的工作原理 三、selinux的启动、关闭与查看 Enforcing和permissive都是临时的,重启还是依据配置文件中,禁用selinux,修改配置文件: 之后重启生效 四、selinux对linux服务的影响...
使用opencv4.7.0部署yolov5
yolov5原理和部署原理就不说了,想了解的可以看看这篇部署原理文章 #include <fstream> #include <sstream> #include <iostream> #include <opencv2/dnn.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/highgui.hpp>/…...
Python - 协程基本使用详解【demo】
一. 前言 协程(Coroutine)是一种轻量级的线程,也被称为用户级线程或绿色线程。它是一种用户态的上下文切换方式,比内核态的线程切换更为轻量级,能够高效的支持大量并发操作。 2. 使用协程的好处 Python 中的协程是通…...
Android MVVM架构模式,详详详细学习
MVVM(Model-View-ViewModel) 是一种基于数据绑定的架构模式,用于设计和组织应用程序的代码结构。它将应用程序分为三个主要部分:Model(模型)、View(视图)和ViewModel(视…...
亿赛通电子文档安全管理系统 RCE漏洞复现
0x01 产品简介 亿赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产&…...
星际争霸之小霸王之小蜜蜂(三)--重构模块
目录 前言 一、为什么要重构模块 二、创建game_functions 三、创建update_screen() 四、修改alien_invasion模块 五、课后思考 总结 前言 前两天我们已经成功创建了窗口,并将小蜜蜂放在窗口的最下方中间位置,本来以为今天将学习控制小蜜蜂,结…...
JS的解析与Js2Py使用
JS的解析与Js2Py使用 JS的解析事件监听器搜索关键字请求关联JS文件 Js2PyJs2Py的简单使用安装Js2Py执行JavaScript代码调用JavaScript函数 Js2Py的应用示例创建JavaScript文件使用JavaScript JS的解析 在一个网站中,登录密码通常是会进行加密操作的,那么…...
Spring Bean的生命周期总结(包含面试题)
目录 一、Bean的初始化过程 1. 加载Spring Bean 2. 解析Bean的定义 3. Bean属性定义 4. BeanFactoryPostProcessor 扩展接口 5. 实例化Bean对象 6. Aware感知 7. 初始化方法 8. 后置处理 9. destroy 销毁 二、Bean的单例与多例模式 2.1 单例模式(Sin…...
SpringjDBCTemplate_spring25
1、首先导入两个包,里面有模板 2、transtion事务 jDbc操作对象,底层默认的是事务: 3、我们java一般对实体类进行操作。 4、第一步写好坐标。 创建一个Account表 数据修改用update 数据进去了...
设计模式——桥接模式
引用 桥我们大家都熟悉,顾名思义就是用来将河的两岸联系起来的。而此处的桥是用来将两个独立的结构联系起来,而这两个被联系起来的结构可以独立的变化,所有其他的理解只要建立在这个层面上就会比较容易。 基本介绍 桥接模式(Br…...
改进YOLO系列:2.添加ShuffleAttention注意力机制
添加ShuffleAttention注意力机制 1. ShuffleAttention注意力机制论文2. ShuffleAttention注意力机制原理3. ShuffleAttention注意力机制的配置3.1common.py配置3.2yolo.py配置3.3yaml文件配置1. ShuffleAttention注意力机制论文 论文题目:SA-NET: SHUFFLE ATTENTION …...
利用Opencv实现人像迁移
前言: Hello大家好,我是Dream。 今天来学习一下如何使用Opencv实现人像迁移,欢迎大家一起参与探讨交流~ 本文目录: 一、实验要求二、实验环境三、实验原理及操作1.照片准备2.图像增强3.实现美颜功能4.背景虚化5.图像二值化处理6.人…...
Lnton羚通算法算力云平台在环境配置时 OpenCV 无法显示图像是什么原因?
问题: cv2.imshow 显示图像时报错,无法显示图像 0%| | 0/1 [00:00<…...
【JavaEE进阶】MyBatis的创建及使用
文章目录 一. MyBatis简介二. MyBatis 使用1. 数据库和数据表的创建2. 创建Mybatis项目2.1 添加MyBatis框架支持2.2 设置MyBatis配置信息 3. MyBatis开发流程4. MyBatis查询数据库测试 三. MyBatis 流程1. MyBatis 查询数据库流程2. MyBatis 框架交互流程图 一. MyBatis简介 M…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
