Linux——文件标识符

news2024/12/26 3:14:30

目录

一、文件基础

二、常见的C语言文件接口

三、系统文件接口 

四、理解语言与系统文件操作的关系

五、如何理解一切皆文件

六、文件标识符再理解


一、文件基础

一个空文件,也会占用磁盘空间,这是因为文件不仅仅有存放在里面的内容,还有属性,比如文件名。创建时间,文件权限等。

文件 = 内容 + 属性。我们对文件的操作,无非是对内容或者对属性的操作。我们知道,=文件是存储在磁盘中的,如果我们打开文件,需要将文件加载到内存中,这样CPU才可以对文件进行处理。打开文件的本质,就是将文件加载到内存

操作系统在运行过程中,可能会打开很多文件,因此操作系统要对打开的文件进行管理。管理的本质操作就是先描述在组织。因此在内核中一定存在已打开文件的结构体,他们依次用链表存储起来,操作系统对文件的管理转为对链表的增删查改。

今天我们着重学系的就是进程与被打开文件的关系。

二、常见的C语言文件接口

  • fopen() —— 打开文件;
    • FILE * fopen ( const char * filename, const char * mode );
  • fclose() —— 关闭文件;
    • int fclose ( FILE * stream );

C语言写入函数

C语言读取函数 

使用fputs写入函数测试下。 

其中“w”权限是写入,没有文件就先创建文件,在写入前会先清空文件内容。在linux中还有一个方法可以进行w写入,就是输出重定向。> 

还有“a”,追加方式,他不会在写入前清空文件内容,而是在文件内容末尾继续追加新内容。linux中的追加重定向为  >> 

重定向这里先了解一下,后续会继续讲解。

三、系统文件接口 

我们知道,打开文件是要将文件加载到内存中,我们之前的操作是使用进程打开文件,进程是没有这么大的权利的,他肯定是调用了操作系统给我们的系统接口。虽然刚刚我们没有调用系统接口,用的是C语言给我们的接口,但其实,C语言打开文件的接口,底层是封装了系统调用接口的!!

系统接口open,第一个参数为路径+文件名,第二个参数是以什么样的方式打开,第三个参数对已创建的文件可以不填,对未创建的文件表示对文件设置什么权限。创建成功返回值为文件描述符file descriptor(简称fd),创建失败返回值为-1。

主要方式如下

  • O_RDONLY:只读模式
  • O_WRONLY:只写模式
  • O_RDWR:可读可写
  • O_APPEND 表示追加,如果原来文件里面有内容,则这次写入会写在文件的最末尾。
  • O_CREAT 表示如果指定文件不存在,则创建这个文件
  • O_EXCL 表示如果要创建的文件已存在,则出错,同时返回 -1,并且修改 errno 的值。
  • O_TRUNC 表示截断,如果文件存在,并且以只写、读写方式打开,则将其长度截断为0。

这些方式是通过位图来实现的,比如O_RDONLY为00000001,O_WRONLY为00000010,O_RDWR为00000100,如此类推,需要使用指定的方式,我们直接进行或运算就好。

运行结果如下,我们创建了log.txt文件,但权限为664,而不是我们代码中的0666,这是因为我们系统权限掩码为0002的原因,0666 &(~0002)= 0664。

写数据的系统接口为write,第一个参数代表往那个文件中写入(是open打开文件获取的文件描述符fd),第二个参数需要写入的字符串,第三个参数为写入的字节数。返回值为实际写入了多少字节的数据。

写入代码

成功写入

我们使用的为O_WRONLY | O_CREAT,只写的方式,没有文件就创建。因此如果再进行写入,并不会将文件内容清空,而是进行覆盖。

如下将str进行修改,再执行命令,查看log.txt的内容,发现good覆盖上了hell 。

 如果我们打开方式  | O_TRUNC,就会在打开前先清空文件。

 如果我们打开方式  | O_APPEND,会从文件结尾处开始写入,这是追加(不清空文件)。

四、理解语言与系统文件操作的关系

经过前面的学习,我们知道C语言文件的处理底层是封装了系统调用接口的,但是C语言fopen返回的是FILE* 指针,而系统open返回的是int类型整数fd,后续也是通过fd来对指定文件做处理的。

那么fd存放的内容是什么呢?我们通过如下代码打印出来看。

发现fd从 3 开始,是连续的小整数。 为什么不从0开始呢,0 1 2这三个去哪里了。如下

进程在运行的时候,默认是把这三小只打开的。但是这三小只不是硬件嘛,怎么跟文件扯上关系了,因为Linux下,一切皆文件。(后面会讲)

我们是通过进程对文件进行处理,那么进程的task_struct里面存在一个files_struct指针指向文件描述符表,里面有很多数据,其中有一个struct file* fd_array[]的数组指针,他指向被打开的文件结构体,这个索引就是文件描述符。如下图所示

但我们查看C标准库,发现这三个变量类型为FILE* 。  

File是C语言提供的结构体类型,fopen的底层是open,那么File结构体里面必定封装了文件描述符。我们通过如下代码也能印证一番

操作系统默认将stdin  stdout  stderr 打开,就是为了让程序员方便进行输入输出代码。就可以直接scanf 和 printf进行输入和显示。我们C语言第一个头文件基本都是stdio.h,stdio就是标准输入输出,C++第一个头文件 iostream,输入输出流。

五、如何理解一切皆文件

操作系统要管理硬件,也是先描述在组织,会将各种硬件使用结构体组织起来,不同的硬件,读写的方法肯定是不一样的,但是struct file里的接口read和write函数指针会指向对应硬件的读写。这样从统一的视角去看待不同硬件。我们也就理解了为何文件先会打开0  1  2这三小只。

六、文件标识符再理解

我们知道了0  1  2号文件标识符分别为stdin,stdout,stderr,也知道了linux一切皆文件,那么我们尝试下使用  read与write + 文件标识符  进行读写来代替(scanf和printf)。

read函数第一个参数fd为文件标识符,第二个参数为读取的数据保存到buf缓冲区中,第三个参数为读取的字节数,返回值为带符号整数(实际读取字节数,失败返回-1)

write函数第一个参数fd也为文件标识符,第二个参数为从buf缓冲区中写入数据到文件,第三个参数为写入的字节数,返回值为带符号整数(实际写入字节数,失败返回-1)

代码如下,从0(stdin)中读取输入到buffer,从buffer写入数据到1(stdout)中。 

成功输出我王慕霸没有开挂!!!! 

我们知道,打开文件fd是从3开始,按顺序依次累加。如果我们先关闭某一个或几个fd文件,那么新打开的文件还是从3开始吗?

使用下面代码测试下

发现是从索引0开始,往后依次查找空位进行放入,比如fd1找到0不存在,就放入到0位置,fd2发现0  1   2都存在,3不存在,就放入3位置。

如果你关掉了1,虽然fd也会放入1位置,但是不会打印,因为1号为标准输出,关闭还打印个啥。但这会发生重定向,也就是打印到新open的文件中,详细内容请看——文件重定向。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1507704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

医学图像分析算法的原理

医学图像分析算法的实现原理涉及数据准备、特征提取、模型选择与训练、模型评估与优化以及部署与应用等多个步骤和技术。通过这些步骤,可以利用机器学习和深度学习技术来帮助医生更准确、更高效地进行医学图像诊断和分析。北京木奇移动技术有限公司,专业…

LeetCode 1315.祖父节点值为偶数的节点和

给你一棵二叉树,请你返回满足以下条件的所有节点的值之和: 该节点的祖父节点的值为偶数。(一个节点的祖父节点是指该节点的父节点的父节点。) 如果不存在祖父节点值为偶数的节点,那么返回 0 。 示例: 输入…

面试官:MySQL的七种日志

哪七种日志日志? 错误日志(error log) error log主要记录MySQL在启动、关闭或者运行过程中的错误信息,在MySQL的配置文件my.cnf中, 可以通过log-error/var/log/mysqld.log 执行mysql错误日志的位置。 慢查询日志&a…

重读 Java 设计模式: 解析单例模式,保证唯一实例的创建与应用

本周工作太忙了,变成了加班狗,下班回来也没时间写,只能利用周末时间写了😭。 好了,言归正传,本次我们先来介绍下设计模式中创建型模式-单例模式。 一、引言 单例模式是设计模式中最简单但又最常用的一种模…

【图论】 【割点】 【双连通分类】LCP 54. 夺回据点

本文涉及知识点 图论 割点 双连通分类 割点原理及封装好的割点类 LeetCode LCP 54. 夺回据点 魔物了占领若干据点,这些据点被若干条道路相连接,roads[i] [x, y] 表示编号 x、y 的两个据点通过一条道路连接。 现在勇者要将按照以下原则将这些据点逐一…

Docker容器Docker桌面配置镜像加速

打开Docker Desktop应用程序,点击设置 具体配置如下: {"builder": {"gc": {"defaultKeepStorage": "20GB","enabled": true}},"experimental": false,"features": {"buil…

基于java的足球联赛管理系统(程序+数据库+文档)

** 🍅点赞收藏关注 → 私信领取本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅** 一、研究背景…

【数据库】软件测试之MySQL数据库练习题目

有表如下: Student 学生表 SC 成绩表 Course 课程表 Teacher 老师表 每个学生可以学习多门课程,每一个课程都有得分,每一门课程都有老师来教,一个老师可以教多个学生 1、查询姓‘朱’的学生名单 select * from Student whe…

「CISP题库精讲」CISP题库习题解析精讲20道

前言 本篇主要对CISP教材第九章《计算环境安全》的一些习题进行讲解,包括20道题,这里只是部分习题,针对第九章可能会多写几章的内容,如果我发布的这些习题里面没有你想找的那道题,你也可以直接私信我,我加…

趣学前端 | Taro迁移完成之后,总结了一些踩坑经验

背景 四月份的时候,尝试将老的移动端项目改造成多端。因为老项目使用的React框架,综合考量,保障当前业务开发的进度同时,进行项目迁移,所以最后选择了Taro框架。迁移成本会低一些,上手快一些。 上个月&am…

新书速览|Vue.js 3.x+Element Plus从入门到精通(视频教学版)

详解Vue.jsElement Plus框架各组件的用法,实战网上商城系统和图书借阅系统开发 本书内容 《Vue.js 3.xElement Plus从入门到精通:视频教学版》通过对Vue.js(简称Vue)的示例和综合案例的介绍与演练,使读者快速掌握Vue.j…

【掌握版本控制:Git 入门与实践指南】配置详解|理解本地仓库结构

🎬慕斯主页:修仙—别有洞天 ♈️今日夜电波:泥中に咲く—ウォルピスカーター 0:34━━━━━━️💟──────── 4:46 🔄 ◀️ ⏸ ▶…

excel批量数据导入时用poi将数据转化成指定实体工具类

1.实现目标 excel进行批量数据导入时,将批量数据转化成指定的实体集合用于数据操作,实现思路:使用注解将属性与表格中的标题进行同名绑定来赋值。 2.代码实现 2.1 目录截图如下 2.2 代码实现 package poi.constants;/*** description: 用…

力扣--动态规划/回溯算法131.分割回文串

思路分析: 动态规划 (DP): 使用动态规划数组 dp,其中 dp[i][j] 表示从字符串 s[i] 到 s[j] 是否为回文子串。预处理动态规划数组: 从字符串末尾开始,遍历每个字符组合,判断是否为回文子串,填充…

像SpringBoot一样使用Flask - 2.静态资源访问及模版

一、安装并导入 render_template 功能:渲染/加载模板,一般是html页面 参数:函数的第一个参数是模板的文件名,必填,后面的参数都是键值对,表示模板中变量对应的值,非必填 (不填界面也不会展示成变…

使用express+nginx+pm2+postman实现推送zip包自动更新前端网页

1.nginx配置将80端口代理到项目的3000端口 server {listen 80; #监听的端口server_name localhost; #监听的域名#charset koi8-r;#access_log logs/host.access.log main;location / {#root html;#index index.html index.html;proxy_pass http://127.0.0.1:3000; #转…

Android App冷启动耗时优化

Android应用启动过程 Android应用启动过程,主要包含app::onCreate及执行前的Application阶段及Activity::onCreate执行之后的Activity阶段,以及两个阶段之间的间隙handleMessage阶段和最终页面渲染上屏完成前数据加载阶段四个区间组成。 具体来看&#x…

如何提高内存和cpu使用率呢?-Linux类资源

最近公司项目上线时,红蓝线巡检时,部分服务器因配置高但使用率低而需要降级。 为了避免降级,如何增加内存和CPU使用率? 这可以通过脚本来实现。 当前服务器操作系统版本:-7_5。 连接服务器后,登录账号。 …

深入理解Debug断点调试技巧

在软件开发过程中,调试是一个非常重要的环节,而使用断点是提高调试效率的关键技巧之一。本文将深入探讨如何利用断点进行高效的调试,常用的快捷键以及一些常见的断点调试技巧。 一、调试技巧: 1. 设置断点:在代码中设…

你配赚米吗?韭菜就在繁荣时进场!防诈P的最简单方法,还不告诉你爸妈?——早读(逆天打工人爬取热门微信文章解读)

你听到哪里好,你去了就是韭菜 引言Python 代码第一篇 人民日报 1460万,保住了!第二篇 人民日报 夜读 每一次努力,都是幸运的伏笔第三篇 人民日报 来啦 新闻早班车要闻社会政策 结尾 “故天将降大任于是人也,必先苦其心…