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

【LINUX】初识文件系统

文章目录

  • 一、前言
  • 二、回顾C语言文件操作
  • 三、初识系统调用
    • open
    • read
    • write
    • close
  • 四、文件系统初识
  • 五、结语

一、前言

二、回顾C语言文件操作

int main()
{FILE* fp = fopen("log.txt", "w");if (fp == NULL){perror("fopen");}int cnt = 0;fputs("hello", fp);fclose(fp);return 0;
}

像我们使用的诸如:fopen、fclose、fputs等一系列函数,其实是C语言提供给我们的。这些函数分别封装了:open、close、write、read等一系列系统调用,向上提供给用户。

三、初识系统调用

open

标志位:
我们在函数中设置参数开关的话,虽然能达到达成某个条件就触发某个功能的效果,但如果传递多个标志位,就会显得拥堵,因此系统用一个整数flags、并用flags的每一个比特位表示一个标志位,这样一个int就可以同时至少传递32个比特位,绝对是够用的了。

open:

int open(const char* pathname,int flags);
int open(const char* pathname,int flags,mode_t mode);

系统调用open让我们能够按照一定方式打开一个文件,并给我们返回一个int类型的值。

pathname:代表文件的路径
flags:就是我们上面提到的标志位,标志位采用宏的方式设置,如O_RDONLY、O_WRONLY、O_TRUNC(清空文件原有内容)、O_APPEND(不清空文件原有内容)
mode:需要我们设置文件的权限(如果需要的话)

open的返回值:

如果使用open打开一个文件并接收这个函数的返回值,我们会发现这个返回值是数字3,那0、1、2去哪里呢?

其实open的返回值被称为 文件标识符 ,之所以从3开始,是因为任何进程在启动的时候都会默认打开三个流:标准输入流、标准输出流,标准错误流,这三个流占用了0、1、2的标识位。

read

ssize_t read(int fd, const void* buf,size_t len);

write

ssize_t write(int fd, const void* buf, size_t count);

close

close(int fd)

实际上,像C语言提供的fopen、fputs、fclose等函数,都是封装了这些系统调用,当我们使用fopen打开一个w文件时,其实在open中传入了多个标志位。不管任何语言如何封装,都是要调用底层的系统调用。

四、文件系统初识

文件如何管理

结合之前讲过的内容,我们知道进程在创建后会有一个task_struct的结构体,里面存放着进程相关内容,而这个结构体里存放着一个 结构体指针 files,这个指针指向的另一个结构体就存放着一个存放文件标识符的数组,并拿这个数组去寻找打开的各种文件。如图所示:

在这里插入图片描述
LINUX下的“一切皆文件”:

如图,我们使用操作系统的本质就是以进程的方式去访问当一个进程创建好以后,如果我们使用键盘和显示器读写操作的时候,进程会统一创建struct file结构体,其中包含文件的基本信息、缓冲区、以及函数指针来指向驱动程序提供操作硬件的方法,尽管各个设备的驱动方法不尽相同,但站在进程的视角,他只需要管理struct file这个结构体,这就是一切皆文件的理解。
在这里插入图片描述
重定向理解:

根据上面的理解,假如有这样一段代码:

int main()
{close(0)//关闭了标准输入流int fd = open("log.txt",O_RDONLY);int a,b;scanf("%d%d",&a,&b);return 0;
}

进程中,文件描述符分配:把下标最小的,没有使用的文件描述符分配给新文件。
由于我们已经把标准输入流(0)关闭,并打开了文件log.txt,此时log.txt的文件标识符就顺利成章的成了(0),因此我们就是从log.txt中读取数据了。

但这样关闭再重定向并不方便,我们也可以使用dup2函数来实现重定向:

int dup2(int oldfd ,int newfd) //将 oldfd 重定向到 newfd

如何做到重定向呢?

在上层无法感知的情况下,在OS内部,更改进程对应的文件描述符表中,特定下标的指向。

缓冲区理解:

先来思考一个问题:

int main()
{fprintf(stdout,"hello world\n");const char* msg = "hello write!\n";write(1,msg,strlen(msg));fork();             return 0;
}

运行两个命令为什么结果不同呢,为什么hello world被打印了两次呢??
在这里插入图片描述
要解释这个问题,我们需要结合重定向和刷新缓冲的策略来理解:

刷新策略:
a.显示器采用的刷新策略:行缓冲
b.普通文件采用的刷新策略:全缓冲

我们的程序里fprintf是C库提供的函数,我们在写入数据的时候,要先将数据写入C库提供的缓冲区内,按照刷新策略将内容拷贝到系统内相应的文件缓冲区,而write直接将数据拷贝到系统内相应的文件缓冲区,直接运行程序,由于显示器是行缓冲策略,因此fork的时候已经把数据都刷新到屏幕了。而重定向后,fprintf采用全缓冲的策略,但由于内容不会达到全缓冲要求,自然不会刷新,数据在C库的缓冲区一直到fork以后才能刷新 ,所谓的刷新即对其中内容清空,这样就会触发写时拷贝,父子进程自然都会刷新一次。
在这里插入图片描述

五、结语

到这里,今天的内容就全部结束了,如果感到对你有所帮助,欢迎三连支持,我们下次再见。

相关文章:

【LINUX】初识文件系统

文章目录一、前言二、回顾C语言文件操作三、初识系统调用openreadwriteclose四、文件系统初识五、结语一、前言 二、回顾C语言文件操作 int main() {FILE* fp fopen("log.txt", "w");if (fp NULL){perror("fopen");}int cnt 0;fputs("…...

金三银四Java面试题及答案整理(2023最新版) 持续更新

作为一名优秀的程序员,技术面试是不可避免的一个环节,一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识。 如果你参加过一些大厂面试,肯定会遇到一些这样的问题: 1、看你项目都用的框架,熟悉 …...

7个角度,用 ChatGPT 玩转机器学习

大家好,我是机器学习科普创作者章北海mlpy,探索更高效的学习方法是我一直等追求。现在的初学者太幸福了,可以利用ChatGPT来帮助你学习机器学习的各个方面。 比如【个人首测】百度文心一言 VS GPT-4这篇文章中,我就用文心一言、GP…...

关于多层板,你了解多少?

01 前言 大家好,我是张巧龙。好久没写原创了,记得之前刚接触PCB时,还在用腐蚀单层板,类似这种。 慢慢随着电子产品功能越来越多,产品越来越薄,对PCB设计要求越来越高了,复杂程度也随之增加。因此…...

使用sqlalchemy-gbasedbt连接GBase 8s数据库

测试环境: 操作系统:CentOS 7.9 64-bit数据库版本:GBase8sV8.8_AEE_3.0.0_1,对应的CSDK版本为3.0.0_1 1,确认安装python3 确认已经安装python3和python3-devel [rootlocalhost test]# python3 -V Python 3.6.8如果…...

前端如何丢掉你的饭碗?

对于后端而言,我们常有“删库跑路”的说法,这说明后端的操作对于信息系统而言通常影响很大,可以轻易使信息系统宕机、崩溃,直接导致项目失败。所以,不要去逼后端程序员! 作为前端程序员,我们似…...

栈、队列、优先级队列的模拟实现

优先级队列的模拟实现栈stack的模拟实现push()pop()top()size()empty()swap()stack总代码队列queue的模拟实现push()pop()front()back()empty()size()swap()queue总代码优先级队列(堆)push()pop()top()empty()size()swap()priority_queue总代码deque的了解栈 在CSTL中栈并不属…...

JMM内存模型

JMM内存模型JMM内存模型定义三大特性原子性可见性有序性volatile语义JMM规则操作系统实现术语缓存一致性要求缓存一致性机制写传播事务串行化重排序as-if-serial 语义(像是有序的)happens-before 原则happens-before 原则的八大子原则内存屏障总结finalf…...

Linux- 系统随你玩之--玩出花活的命令浏览器-双生姐妹花

文章目录1、背景2、命令浏览器-双生姐妹花2.1、姐妹花简介2.2 、验名正身2.3、常用功能选项3、常用实操3.1、发送请求获取文件3.1.1、抓取页面内容到一个文件中3.1.2、多个文件下载3.1.3、下载ftp文件3.1.4、断点续传3.1.5、上传文件3.1.6、内容输出3.2 、利用curl测试接口3.3 …...

【深度学习】基于Hough变化的答题卡识别(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。⛳座右铭&#…...

Linux - 进程控制(创建和终止)

1.进程创建fork函数初识 在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。返回值:子进程返回0,父进程返回子进程id,出错返回-1getpid()获取子进程id&#xff0c…...

依赖注入~

依赖注入之setter注入: 依赖注入是IOC具体的一种实现方式, 这是针对资源获取的方式角度来说的,之前我们是被动接受,现在IOC具体的实现叫做依赖注入,从代码的角度来说,原来创建对象的时候需要new&#xff0…...

【嵌入式硬件芯片开发笔记】HART协议调制解调芯片AD5700配置流程

【嵌入式硬件芯片开发笔记】HART协议调制解调芯片AD5700配置流程 XTAL_EN接地,CLK_CFG的两个引脚由同一个GPIO控制 初始时HART_CLK_CFG输出低电平 由RTS引脚控制调制/解调。当RTS处于高电平时,为解调(输入);否则为调…...

Go语言异步下载视频

异步下载mp4视频列表 下面是一个简单的Go语言示例,用于异步下载视频。我们将使用goroutines来实现异步下载,并使用sync.WaitGroup来等待所有下载任务完成。此示例依赖于net/http包来执行HTTP请求。 package mainimport ("fmt""io"…...

前缀树(字典树/Trie) -----Java实现

目录 一.前缀树 1.什么是前缀树 2.前缀树的举例 二.前缀树的实现 1.前缀树的数据结构 1.插入字符串 2.查找字符串 3.查找前缀 三.词典中最长的单词 1.题目描述 2.问题分析 3.代码实现 一.前缀树 1.什么是前缀树 字典树(Trie树)是一种树形…...

​申请专利需要具备什么条件

​申请专利需要具备什么条件 在我国,如果创造出来了新的发明都可以申请专利权,一旦申请成功之后,自己的发明就受到了法律的保护,任何人不得以违法的手段进行侵犯。那么申请专利需要具备什么条件?今天律赢时代网就为大家…...

【C++】一篇带你搞懂C++“引用”

前言在C语言的学习中,并没有引用这个概念,但是在C中,加入了引用这个概念,说明引用也是很重要的,但是我们怎么理解引用呢?我是这么理解的,例如在水浒传中,108个英雄好汉都是自己的外号…...

蓝桥杯刷题冲刺 | 倒计时19天

作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.抓住那头牛2.排列序数1.抓住那头牛 题目 链接: 抓住那头牛 - C语言网 (dotcpp.com…...

Java每日一练(20230321)

目录 1. 出现次数最多的字符 🌟 2. 最后一个单词的长度 🌟 3. 两数之和 🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 出现次数最多的字符并…...

【三维几何学习】从零开始网格上的深度学习-3:Transformer篇(Pytorch)

本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052 从零开始网格上的深度学习-3:Transformer篇引言一、概述二、核心代码2.1 位置编码2.2 网络框架三、基于Transformer的网格分类3.1 分类结果3.2 全部代码引言 本文主要内容如下&#…...

一、基础算法3:二分 模板题+算法模板(数的范围,数的三次方根)

文章目录算法模板整数二分算法模板浮点数二分算法模板模板题数的范围原题链接题目题解数的三次方根原题链接题目题解算法模板 整数二分算法模板 bool check(int x) {/* ... */} // 检查x是否满足某种性质// 区间[l, r]被划分成[l, mid]和[mid 1, r]时使用: int b…...

Spring 源码解析 - Bean创建过程 以及 解决循环依赖

一、Spring Bean创建过程以及循环依赖 上篇文章对 Spring Bean资源的加载注册过程进行了源码梳理和解析,我们可以得到结论,资源文件中的 bean 定义信息,被组装成了 BeanDefinition 存放进了 beanDefinitionMap 容器中,那 Bean 是…...

移除元素(双指针)

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的…...

76.qt qml-QianWindow开源炫酷界面框架(支持白色暗黑渐变自定义控件均以适配)

界面介绍界面支持: 透明 白色 黑色 渐变 单色 静态图 动态图侧边栏支持:抽屉、带折叠、多模式场景控件已集成: 暗黑风格 高亮风格、并附带个人自定义控件及开源demo白色场景如下所示:单色暗黑风格如下所示:用户自定义皮肤如下所示:皮肤预览如下所示:b站入口:https://www.bilibi…...

Python生日蛋糕

目录 前言 底盘 蛋糕 蜡烛 祝福 前言 Hello,小伙伴们晚上好吖!前两天博主满20岁啦(要开始奔三辽呜呜呜),这几天收到了不少小伙伴们的祝福,浪漫的小博主想送给大家一份不一样的生日蛋糕&#xff0c…...

QT 如何提高 Qt Creator 的编译速度

如何提高编译速度,貌似是一个老生常谈的话题。对于Qter而言,如何提高QT Creator 的编辑速度是一直都是大家所期盼的。本文也是查阅了各路大神的方法后整理出来的,希望对各位有所帮助。 1、在*.pro文件添加预编译机制 QT官方给出的示例&…...

STM32之震动传感器、继电器介绍及实战

目录 一、震动传感器介绍及实战 二、编程代码实现 1、gpio.c---------初始化GPIO口引脚函数 2、调用中断服务函数 3、中断服务函数 4、中断服务回调函数 5、把上述的中断服务回调函数,放入main主函数里 6、结果演示 三、继电器介绍及实战 一、震动传感器介…...

RK3588平台开发系列讲解(显示篇)RK3588 平台 的DP介绍

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、功能特性二、 DP 输⼊三、DP 输出四、 代码路径沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 RK3588 平台 DP 的使⽤与调试⽅法。 一、功能特性 RK3588 的 DP ⽀持 1.4a 版本的 DP 协议,最…...

【Java】i++和++i的实现原理

文章目录 i++案例反编译分析扩展 x = x++我们接下来从字节码层面分析: 不了解字节码的可以参考这篇:【精通JVM】字节码指令全解 i++案例 package org.example;public class Main {public static void main...

第十四届蓝桥杯三月真题刷题训练——第 18 天

目录 第 1 题:排列字母 问题描述 运行限制 代码: 第 2 题:GCD_数论 问题描述 输入格式 输出格式 样例输入 样例输出 评测用例规模与约定 运行限制 第 3 题:选数异或 第 4 题:背包与魔法 第 1 题&#x…...