当前位置: 首页 > news >正文

【Linux】文件

其实我们在C语言就学过文件操作,但是从语言的角度,我们只是说会用了关于文件的一些操作和函数,但其实它究竟是怎么回事我们其实并不明白,那么当我们学习到Linux操作系统的时候,我们才能更加深入的去了解这文件究竟是怎么回事

那么我们需要首先明确一些概念:文件=内容加属性,不能说我这个文件是空,那么就不占空间;访问文件都得先打开,然后通过执行代码的方式去修改文件内容,也就是文件要被加载到内存中;是进程打开的文件并且一个进程可以打开多个文件;一个时间段内,可能有多个进程,操作系统要管理这些进程,同时也可能有多个被打开的文件,操作系统也要管理这些文件,那么如何管理呢?先描述,再组织,就是说,操作系统要给每个文件创建一个结构体对象,对文件的管理就变成了对于结构体的管理。

那么下面先回忆一下之前C语言用的一些函数:

首先就是fopen,并且我记得当时选项w最为奇怪,因为每一个用,那么之前的数据都会不见了,这不是跟我们的输出重定向(>)很像吗

意思是:截断文件到长度0或者如果没有那么创建新文件

我们原来都是这么用的:

我们说如果w选项,当前路径下没有这个文件,那么就会在当前路径下去创建,那么进程怎么知道当前在那个路径下呢?我们说过进程启动时,会记录下自己的路径

所以进程就会在这个路径下创建新文件

并且我们还有一个选项a,叫做append(附加),这不是跟追加重定向(>>)很像吗

下面我们再看一下fwrite这个函数

基本的使用就是这样

我们可以确定的是,输出一些东西必须要知道要向那个文件中输出,就连显示器也不例外,因为Linux下一切皆文件,那么平时用printf/scanf的时候也没加文件啊,那是因为stdout,stdin和stderror是程序默认打开的,可以直接使用

并且fprintf是要加文件的,所以printf就是封装了fprintf,并且文件指针是stdout

我们知道,对硬件进行修改只能通过操作系统,所以操作系统就必须提供系统调用接口,像fopen这样的库函数是语言层面的概念,为了实现语言的跨平台性和可移植性,所以它要封装系统调用,并且在不同的操作系统要封装各自的系统调用。所以我们下面就介绍一下Linux操作系统关于文件操作的系统调用open和close

open的第一个参数就是路径,第二个参数就是之前说的类似于“w“、“a”的一些选项,常见的打开标志有:

O_TRUNC:打开文件前会清空文件

第三个参数就是要给文件设置的权限,返回值就是文件描述符,其实就是一个整数,通过这个整数,就可以确定这个文件

当我们用第一个open时,并且路径中没有,它需要创建,这时我们可以看到文件的权限是乱码

所以我们一般使用第二个,权限计算还是给定的权限减去权限掩码,比如:

并且通过umask()函数我们还可以在程序中设置权限掩码,并且这个权限掩码只在当前程序下生效

知道了这些宏的意义,我们就可以和之前fopen的不同选项的功能对应上了,其实“w”选项不就是这三个选项的叠加吗

其实如果只有前两个的话原始文件中的内容并不会清空,而新内容就从头开始进行覆盖,就是这样一种现象

选项“a”不就是这三个选项的叠加吗

并且追加内容时会在下一行追加

所以我们说fopen底层就是封装了open,并且不同的选项底层就对应了不同的宏,我们上面说stdin、stdout、stderr每个程序都会默认打开,并且它们的类型是FILE*,这是C语言层面的类型,本质就是一个结构体,既然Linux要通过文件描述符来确定一个文件,C语言要通过FILE*的对象,所以FILE*结构体中肯定有文件描述符

我们可以连续创建一些文件看看它们的文件描述符之间有什么规律

文件描述符是从3开始依次增长,那0,1,2呢?其实0,1,2就分别是程序默认打开的stdin,stdout和stderr,这个数字其实就是数组下标,就是说:一个进程的PCB中存着此进程打开的文件列表的指针,通过这个指针可以找到打开的文件列表,而这个文件列表中也是存着每个文件管理的指针,通过这个指针就可以找到操作系统对文件进行管理的结构体了

我们可以关闭stdout试一试,还不能关这个,因为一旦关了就打印不出东西来了,我们卡伊关掉stdin,新打开的文件的文件描述符就会从最小的没用到的0开始

这个_fileno就是FILE*结构体中文件描述符的名字

所以我们就可以利用上面的规则实现重定向,比如printf默认向stdout中打印,其实它认识的是文件描述符为1,所以我们就可以这样,将想打印的内容打印到一个文件中而不是显示器

这样也确实比较麻烦,并且还要了解文件描述符的分配规则,其实也不知可以这么做,系统还提供了系统调用来供我们使用,这个就是通过拷贝指针来实现目的

于是我们就可以这么用:

相关文章:

  • 探究 Cosmos Hub 作为国家行为者的可能性
  • Python使用动态代理的多元应用
  • Qt 控件提升
  • HOT100与剑指Offer
  • Oracle中TAF与SCANIP全面解析
  • Usage - hackthebox
  • PyQt5创建与MySQL数据库集成的应用程序
  • 利用ssh远程安装显卡驱动
  • 铁塔基站用能监控能效解决方案
  • 链表(2)反转链表
  • 字符串匹配算法(三)Trie树算法
  • 长难句打卡5.31
  • 闽盾杯 2021 DNS协议分析
  • 初识Sass
  • openfiler安装部署-1
  • 【Amaple教程】5. 插件
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • 2017前端实习生面试总结
  • android 一些 utils
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Python 基础起步 (十) 什么叫函数?
  • sessionStorage和localStorage
  • spark本地环境的搭建到运行第一个spark程序
  • springboot_database项目介绍
  • vuex 学习笔记 01
  • vue自定义指令实现v-tap插件
  • XML已死 ?
  • 对象引论
  • 正则与JS中的正则
  • 智能网联汽车信息安全
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • # wps必须要登录激活才能使用吗?
  • #### golang中【堆】的使用及底层 ####
  • (10)STL算法之搜索(二) 二分查找
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (第一天)包装对象、作用域、创建对象
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (力扣)循环队列的实现与详解(C语言)
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (七)Java对象在Hibernate持久化层的状态
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • (转)四层和七层负载均衡的区别
  • .NET CF命令行调试器MDbg入门(一)
  • .NET CORE Aws S3 使用
  • .net framework profiles /.net framework 配置
  • .NET Framework、.NET Core 、 .NET 5、.NET 6和.NET 7 和.NET8 简介及区别
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET 指南:抽象化实现的基类
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • .NET中分布式服务