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…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...