【Linux】封装一下简单库 理解文件系统

news2024/9/23 23:25:06

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、封装一下简单库

二、理解一下stdin(0)、stdout(1)、stderr(3)

2.1、为什么要有0、1、2呢?

2.2、特点

2.3、如果我想让2也和1重定向到一个文件中?

三、理解文件系统

3.1、看看物理磁盘

3.2、了解一下磁盘的储存结构

3.3、对磁盘的存储进行逻辑抽象

3.4、找到一个文件的步骤:

3.5、逆向的路径解析 --- OS自己做的

总结



前言

世上有两种耀眼的光芒,一种是正在升起的太阳,一种是正在努力学习编程的你!一个爱学编程的人。各位看官,我衷心的希望这篇博客能对你们有所帮助,同时也希望各位看官能对我的文章给与点评,希望我们能够携手共同促进进步,在编程的道路上越走越远!


提示:以下是本篇文章正文内容,下面案例可供参考

一、封装一下简单库

Stdio.h
#pragma once
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define LINE_SIZE 1024
#define FLUSH_NOW  1
#define FLUSH_LINE 2
#define FLUSH_FULL 4

// 文件结构体类型
struct _myFILE
{
    unsigned int flags;
    int fileno;
    // 缓冲区
    char cache[LINE_SIZE];// 文件的缓冲区
    int cap;
    int pos; // 下次写入的位置
};

typedef struct  _myFILE myFILE;

myFILE* my_fopen(const char* path, const char* flag);
void my_fflush(myFILE* fp);
ssize_t my_fwrite(myFILE* fp, const char* data, int len);
void my_fclose(myFILE* fp);
Mystdio.c
#define _CRT_SECURE_NO_WARNINGS 1

#include "mystdio.h"

myFILE* my_fopen(const char* path, const char* flag)
{
    int flag1 = 0;// 打开文件的模式
    int iscreate = 0;// 是否要创建文件
    mode_t mode = 0666;// 文件的初始权限
    if (strcmp(flag, "r") == 0)
    {
        flag1 = (O_RDONLY);
    }
    else if (strcmp(flag, "w") == 0)
    {
        flag1 = (O_WRONLY | O_CREAT | O_TRUNC);
        iscreate = 1;
    }
    else if (strcmp(flag, "a") == 0)
    {
        flag1 = (O_WRONLY | O_CREAT | O_APPEND);
        iscreate = 1;
    }
    else
    {
    }

    int fd = 0;
    // 根据是否要创建文件来使用不同的open()函数
    if (iscreate)
        fd = open(path, flag1, mode);
    else
        fd = open(path, flag1);

    if (fd < 0) return NULL;

    myFILE* fp = (myFILE*)malloc(sizeof(myFILE));
    if (!fp) return NULL;

    fp->fileno = fd;
    fp->flags = FLUSH_LINE;// 行刷新

    fp->cap = LINE_SIZE;// 缓冲区的容量
    fp->pos = 0;// 当前写入文件的位置

    return fp;
}

void my_fflush(myFILE* fp)
{
    write(fp->fileno, fp->cache, fp->pos);
    fp->pos = 0;
}

// 写入数据:把用户将数据写入stdout文件当中(语言级的文件缓冲区内),将语言级的缓冲区内的内容拷贝到OS的内核级的缓冲区内
ssize_t my_fwrite(myFILE* fp, const char* data, int len)
{
    // 写入操作本质是拷贝, 如果条件允许,就刷新,否则不做刷新
    // 将数据拷贝到语言级的缓冲区
    memcpy(fp->cache + fp->pos, data, len); //肯定要考虑越界, 自动扩容
    fp->pos += len;

    if ((fp->flags & FLUSH_LINE) && fp->cache[fp->pos - 1] == '\n')
    {
        // 将语言级的缓冲区的数据拷贝到OS中对应的文件的内核级缓冲区
        my_fflush(fp);
    }

    return len;
}

void my_fclose(myFILE* fp)
{
    my_fflush(fp);
    close(fp->fileno);
    free(fp);
}
Testfile.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "mystdio.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define FILE_NAME "log.txt"

int main()
{
    myFILE* fp = my_fopen(FILE_NAME, "w");
    if (fp == NULL) return 1;

    const char* str = "hello bit";
    int cnt = 10;
    char buffer[128];
    while (cnt)
    {
        sprintf(buffer, "%s - %d", str, cnt);
        my_fwrite(fp, buffer, strlen(buffer)); // strlen()+1不需要
        cnt--;
        sleep(1);
        my_fflush(fp);
    }

    my_fclose(fp);
    return 0;
}

结论:C语言为什么要在FILE中提供用户级缓冲区 ----- 为了减少底层调用系统调用的次数,让使用C语言的IO函数(printf,fprintf)效率更高。

二、理解一下stdin(0)、stdout(1)、stderr(3)

2.1、为什么要有0、1、2呢?

  • 0、1 -----> 用户要知道数据从哪里来,数据要到哪里去。
  • 2 -----> 把正确的信息和错误的信息区分开来。

2.2、特点

我们是要将原本打印在屏幕行的数据打印在 log.txt 里,为什么stderr还在屏幕上显示?

标准输出重定向的本质:更改文件描述符表中下标为1的内容(地址)。下标为1的内容原先是显示器文件的地址,现在更改为 log.txt 文件的地址。

下标为1和下标为2的空间的地址都是指向显示器文件的;下标为2的空间中的地址没有被改变,依然指向显示器文件的地址。所以,stderr仍然打印在屏幕上。

2.3、如果我想让2也和1重定向到一个文件中?

./a.out 1>ok.log 2>err.log

将下标为1的内容更改成 ok.log 文件的地址;将下标为2的内容更改成 err.log 文件的地址;将正确和错误的信息分离开来。

./a.out 1>all.log 2>&1

将下标为1的内容更改成 all.log 文件的地址;取下标为1的内容的地址更改下标为2的内容;从而使2和1重定向到一个文件中。

C语言中的 perror 本质是向2对应的文件打印,printf() 本质是向1对应的文件打印。

C++中的 cout 对应的是 printf;cerr 对应的是 perror。

三、理解文件系统

3.1、看看物理磁盘

3.2、了解一下磁盘的储存结构

3.3、对磁盘的存储进行逻辑抽象

假如:一个磁盘有800GB,我们把800GB分为4个区,每个区200GB,再将每个分区分组,我们只要管理好每一个分组,就能管理好一个分区,进而管理好磁盘。

格式化:在每一个分区内部分组,然后写入文件系统的管理数据。

文件在磁盘存储的本质:=文件的内容+文件的属性数据。

Linux文件系统特定:文件内容和文件属性分开存储。

  • Block Group:许多个数据块(4kb)组成,用来存放文件的内容。
  • 超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:block 和 inode的总量, 未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了
  • GDT,Group Descriptor Table:块组描述符,描述整个分组里的使用情况,比如:一共有多少inode,一共有多少数据块呢?inode、数据块和Bitmap已经被占据了多少呢?那么下一个被分配的inode编号是几?由GDT来进行统一管理。
  • 块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用(比特位的位置,表示块号。比特位的内容,表示该块是否被占用。)
  • inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。
  • i节点表:存放文件属性,如:文件大小,所有者,最近修改时间等。
  • 超级块(Super Block):不是每个分组都有的。分配inode编号的范围。如果一个磁盘的某一分组的Super Block不小心被刮花了,那么可以通过其它分组的Super Block来恢复。

我们寻找文件的时候,都必须先得到inode的编号。inode编号是以分区为单位的!

但是你凭什么直接拿到inode的编号,我们一直使用的都是文件名啊!!!!

谈谈目录:

目录 = 文件属性 + 文件内容。    目录也是一个文件。

  1. 一个目录下不能建立同名文件;
  2. 查找文件的顺序,文件名 -----> inode的编号;
  3. 目录的r,本质是是否允许我们读取目录的内容;目录的内容是:文件名与inode的映射关系!!!
  4. 目录的w,新建文件,最后一定要向当前所处的目录内容中写入,文件名与inode的映射关系。

如何理解文件的增删查改呢?

  • 增:建立文件名与inode的映射关系。
  • 删:将该文件的inode编号在位图中对应的比特位置为0。

我们常说的将系统格式化,恢复出厂设置,其实就是将位图中的1全部置为0。

3.4、找到一个文件的步骤:

我们找到一个指定的文件 -----> 文件所在的目录 ------> 打开目录 -----> 根据文件名与inode的映射关系 -----> 找到目标文件inode。

但是有一个前提是:inode的编号是不能跨分区的,我们怎么才能知道我们的文件在哪一个分区内呢?

结论:比如:我用的云服务器一般只有一个盘(vda),一个盘对应了一个分区,在Linux中要访问一个分区其实要将这个分区进行挂载的,挂载也就是将一个磁盘分区和文件系统的一个目录进行关联,所以,未来进入分区,其实是进入一个指定的目录的。

分区 ----> 写入文件系统(格式化)(就是将在分组中写入管理的数据,但是此时这个分区还不能使用) ----> 挂载到指定目录下 ----> 进入该目录,自然就在该目录的分区下 ----> 在指定的分区中进行文件操作。

这也就是我们在Linux系统中,定位一个文件,在任何时候,都要有路径的原因!!!因为有路径,你就知道在哪个分区。

3.5、逆向的路径解析 --- OS自己做的

要打开当前目录,当前目录也是一个文件,你得找到当前目录的inode,那么你就得找到当前目录的上级目录;所以Linux在找到任何一个路径下的一个文件时,Linux系统一定要给我们逆向的递归式的路径解析;直到找到了根目录,就类似于找到了一个递归出口一般,然后再反向的逐次打开我们的文件。

逆向的路径解析,我们的Linux系统会一直做,那么必然会导致效率方面下降,所以Linux系统为了支持逆向路径解析,系统会把已经解析过的路径给我们进行缓存起来;那么将来要打开文件时,把要解析的路径,先在缓存里找,找不到,再解析。


总结

好了,本篇博客到这里就结束了,如果有更好的观点,请及时留言,我会认真观看并学习。
不积硅步,无以至千里;不积小流,无以成江海。

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

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

相关文章

护眼台灯哪个牌子好?护眼灯十大品牌推荐,绝对真香!

对于有孩子的家庭&#xff0c;特别是阅读爱好者&#xff0c;晚上阅读时的光线问题至关重要。昏暗环境长时间阅读&#xff0c;会严重伤害孩子的眼睛。因此&#xff0c;选择一款合适的护眼台灯显得尤为重要。但市场上品牌众多&#xff0c;护眼台灯哪个牌子好?这往往让人难以抉择…

【Tomcat 文件读取/文件包含(CVE-2020-1938)漏洞复现】

文章目录 前言 一、漏洞名称 二、漏洞描述 三、受影响端口 四、受影响版本 五、漏洞验证 六、修复建议 前言 近日在做漏扫时发现提示服务器存在CVE-2020-1938漏洞&#xff0c;故文章记录一下相关内容。 一、漏洞名称 Tomcat 文件读取/文件包含漏洞(CVE-2020-1938) 二、漏洞描…

a == 1 a== 2 a== 3 返回 true ?

1. 前言 下面这道题是 阿里、百度、腾讯 三个大厂都出过的面试题&#xff0c;一个前端同事跳槽面试也被问了这道题 // &#xff1f; 位置应该怎么写&#xff0c;才能输出 trueconst a ?console.log(a 1 && a 2 && a 3) 看了大厂的面试题会对面试官的精神…

这款开发工具大大降低IoT开发门槛!完全开源,上手超简单

对开发者来说&#xff0c;IoT 开发的难点是什么&#xff1f;首先&#xff0c;IoT 涉及到多个领域和多种开发技术&#xff0c;每一层的技术接口、协议都需要跨平台、跨领域、跨系统的合作协同&#xff1b;在互联互通方面&#xff0c;智能设备间的兼容性亟待进一步地打通融合&…

ANSYS 2023版 下载地址及安装教程

ANSYS是一款著名的工程仿真软件&#xff0c;广泛应用于航空航天、汽车、能源和制造等领域。它为工程师和设计师提供了强大的建模、分析和优化工具&#xff0c;可以帮助他们预测和优化产品的性能。 ANSYS提供了广泛的模拟功能&#xff0c;包括结构力学、流体力学、电磁场和热传…

Unity | Shader基础知识(第十二集:颜色混合)

目录 前言 一、日常生活中的常见现象 二、unity自带的一个结构体&#xff08;表面着色器SurfaceOutputStandard&#xff09; 三、自己写一个颜色混合的Shader 1.只加基础颜色Albedo 2.加入法线 3.加入光滑度 4.加入金属度 5.加入自发光 四、作者的话 前言 shader里每一…

2024第十五届蓝桥杯 JAVA B组

目录 前言&#xff1a;试题 A: 报数游戏试题 B: 类斐波那契循环数试题C:分布式队列 前言&#xff1a; 没参加这次蓝桥杯算法赛&#xff0c;十四届蓝桥杯被狂虐&#xff0c;对算法又爱又恨&#xff0c;爱我会做的题&#xff0c;痛恨我连题都读不懂的题&#x1f62d;,十四届填空只…

计算方法实验5:对鸢尾花数据集进行主成分分析(PCA)并可视化

任务 iris数据集包含150条数据&#xff0c;从iris.txt读取&#xff0c;每条数据有4个属性值和一个标签&#xff08;标签取值为0&#xff0c;1&#xff0c;2&#xff09;。要求对这150个4维数据进行PCA&#xff0c;可视化展示这些数据在前两个主方向上的分布&#xff0c;其中不…

鸿蒙原生应用元服务-访问控制(权限)开发Stage模型向用户申请授权

一、向用户申请授权 当应用需要访问用户的隐私信息或使用系统能力时&#xff0c;例如获取位置信息、访问日历、使用相机拍摄照片或录制视频等&#xff0c;应该向用户请求授权。这需要使用 user_grant 类型权限。在此之前&#xff0c;应用需要进行权限校验&#xff0c;以判断当前…

Golang教程一(环境搭建,变量,数据类型,数组切片map)

目录 一、环境搭建 1.windows安装 2.linux安装 3.开发工具 二、变量定义与输入输出 1.变量定义 2.全局变量与局部变量 3.定义多个变量 4.常量定义 5.命名规范 6.输出 格式化输出 7.输入 三、基本数据类型 1.整数型 2.浮点型 3.字符型 4.字符串类型 转义字…

贝叶斯公式中的先验概率、后验概率、似然概率

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

Neo4j 图形数据库中有哪些构建块?

Neo4j 图形数据库具有以下构建块 - 节点属性关系标签数据浏览器 节点 节点是 Graph 的基本单位。 它包含具有键值对的属性&#xff0c;如下图所示。 NEmployee 节点 在这里&#xff0c;节点 Name "Employee" &#xff0c;它包含一组属性作为键值对。 属性 属性是…

华为HarmonyOS 4.2公测升级计划扩展至15款新机型

华为近日宣布&#xff0c;HarmonyOS 4.2操作系统的公测升级计划将扩展到包括华为P50系列在内的15款设备。这一更新旨在为用户提供更优化的系统性能和增强的功能。 参与此次公测的机型包括华为P50、华为P50 Pro及其典藏版、华为P50E、华为P50 Pocket及其艺术定制版、华为nova系…

Unity开发HoloLens2应用时,用VisualStudio进行真机在线Debug调试

一、需求 用Unity开发的应用&#xff0c;部署到真机设备出现启动崩溃&#xff0c;此时可以用在线调试&#xff0c;排查错误。 二、开发环境说明 MRholoLens2 Unity 2021.3.18 Win Win10 VS vs2022 三、调试操作步骤 1、HoloLens2与电脑的连接&#xff0c;Wifi连接&…

不是所有商业模式都叫传销!七星创客模式!

“商业模式是否等同于拉人头、传销&#xff1f;”近期&#xff0c;这一疑问在许多人心中萦绕。似乎每当提及商业模式&#xff0c;总有些人会将其与拉人头、传销等概念联系起来&#xff0c;仿佛所有的商业模式都带有某种负面色彩。 然而&#xff0c;商业模式的内涵远非如此单一。…

MCU的最佳存储方案CS创世 SD NAND

MCU的最佳存储方案CS创世 SD NAND 写在最前面MCU是什么CS创世 SD NAND 6大优势 写在最前面 转载自 雷龙官网 MCU是什么 大家都知道MCU是一种"麻雀"虽小&#xff0c;却"五脏俱全"的主控。它的应用领域非常广泛&#xff0c;小到手机手表&#xff0c;大到航空…

【服务器部署篇】Linux下Jenkins安装和配置

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0c;产…

使用PL\SQL将Excel表格导入到oracle数据库中

因为要测试生产问题&#xff0c;需要把生产上oracle导出数据导入到测试环境oracle数据库中&#xff0c;尝试了N种方法&#xff0c;发现使用PL\SQL 的ODBC 方法比较好用 1、开始 首先使用plsqldev里面的&#xff0c;工具--》下面的odbc导入器 2、配置 点击之后&#xff0c;会…

获取jd.item_get-获得京东商品详情API接口请求参数请求接入示例免费接入KEY演示

京东商品详情API接口的主要作用是&#xff1a; 获取基本信息&#xff1a;包括商品的名称、品牌、产地和规格参数等&#xff0c;这些信息有助于构建商品的基本档案。价格信息获取&#xff1a;可以了解到商品的原价、促销价以及参与的各种活动信息&#xff0c;这对于制定销售策略…

DePT: Decoupled Prompt Tuning 论文阅读

DePT: Decoupled Prompt Tuning 了论文阅读 Abstract1. Introduction2. Methodology2.1. Preliminaries2.2. A Closer Look at the BNT Problem2.3. Decoupled Prompt Tuning 3. Experiments5. Conclusions 文章信息&#xff1a; 原文链接&#xff1a;https://arxiv.org/abs/…