【Linux修炼】12.深入了解系统文件

news2024/11/26 19:46:47

在这里插入图片描述每一个不曾起舞的日子,都是对生命的辜负。

文件fd

  • 一. 重新谈论文件
    • 1. 共识的问题
    • 2. 重谈C语言文件操作
      • 2.1 概要
      • 2.2 C语言文件实操
      • 2.3 OS接口open的使用(比特位标记)
      • 2.4 写入操作
      • 2.5 追加操作
      • 2.6 只读操作
  • 二. 如何理解文件
    • 1. 提出问题
    • 2. 文件描述符fd
  • 三. 文件fd的分配规则
  • 四. 重定向
    • 1. 什么是重定向
    • 2. dup2 系统调用的重定向
    • 3. 理解:>、>>、<
  • 五. 如何理解Linux一切皆文件

一. 重新谈论文件

1. 共识的问题

在这篇正式开始之前,大家要有一些共识性的问题:

  1. 空文件也要在磁盘占据空间
  2. 文件 = 内容 + 属性
  3. 文件操作 = 对内容+对属性+对内容和属性的操作
  4. 标定一个问题,必须使用:文件路径+文件名【唯一性】
  5. 如果没有指明对应的文件路径,默认是在当前路径(进程当前路径)进行文件访问
  6. 当我们把fopen、fclose、fread、fwrite等接口写完之后,代码编译之后,形成二进制可执行程序之后,但是没有运行,文件对应的操作有没有被执行呢?没有,对文件的操作的本质是进程对文件的操作,因此没有运行不存在进程,所以不会被执行。
  7. 一个文件如果没有被打开,可以直接进行文件访问吗?不能!一个文件要被访问,就必须先被打开!(打开的方式:用户进程+OS)

那是不是所有磁盘的文件都被打开呢?显然不是这样!因此我们可以将文件划分成两种:a.被打开的文件b.没有被打开的文件 。对于文件操作,一定是被打开的文件才能进行操作,本篇文章只会讲解被打开的文件。

  • 文件操作的本质:进程和被打开文件的关系

2. 重谈C语言文件操作

2.1 概要

  1. 语言有文件操作接口、C++有文件操作接口,Java、Python、php、go、shell都有文件操作接口,他们实际上的底层都是相同的函数接口,因为都需要通过OS调用。
  2. 文件在磁盘上,磁盘是硬件,只有操作系统有资格访问,所有人想访问磁盘都不能绕过操作系统,必须使用操作系统调用的接口,即OS会提供文件级别的系统调用接口。
  3. 所以上层语言无论如何变化,库函数底层必须调用系统调用接口。
  4. 库函数可以千变万化,但是底层不变,因此这样能够降低学习成本—>学习不变的东西。

2.2 C语言文件实操

复习一下:下面fp按顺序对应以下三个操作依次:写入文件、打印文本信息、追加文本信息到文件中。

image-20221229190352076

  • 细节问题:以w方式单纯的打开文件,c会自动清空内部的数据。

对于C语言调用的fopen打开文件,实际上底层调用的是操作系统的接口open,其他语言也是这样,只不过语言级别的接口是多了一些特性,下面就看看:man 2 open image-20221230105126795

对于flag标记位,一般来说对于C语言,一个int类型代表一个标记位,那如果要传10个标记位呢?对于整形来说,实际上有32个比特位,那是不是可以将每一个比特位赋予特定的含义,通过比特位传递选项,从而实现对应的标记呢?一定是可以的。因此在介绍open函数之前,先来介绍一下标记位的实现:

  • 注意:一个比特位一个选项,不能重复。(标记位传参)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N9EuNNks-1672976248068)(https://newcfy.oss-cn-beijing.aliyuncs.com/img2/202212301105163.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QFmb56Rl-1672976248068)(https://newcfy.oss-cn-beijing.aliyuncs.com/img2/202212301106374.png)]

因此我们再看这个open函数,就明白了是什么含义,就是通过不同的flags,传入不同的标记位,那接下来看看open函数怎么用:

2.3 OS接口open的使用(比特位标记)

不废话,我们知道了上面用的头文件就直接开始使用了:

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

第一个函数是在文件已经存在的基础上使用的,如果不存在源文件,那么就需要用第二个函数,即第二个函数如果文件不存在就会自动创建文件。image-20221230124013820

这样就能创建出权限为0666的log.txt了。image-20221230124118857
fd的值也是有讲究的,这里看一下fd的值:image-20221230124344591

image-20221230124417558

这个值暂时记住,下面将会讲到。

2.4 写入操作

对于C语言来讲,除了打开关闭,还有写入fwrite等函数接口,因此对于OS也存在一个接口:writeimage-20221230125103454

无论这个buf是什么类别,在OS看来都是二进制!至于这个类别是文本还是图片,都是由语言本身决定的。image-20221230125553481

下面开始:image-20221230134029791

image-20221230134107554

可以看出,对于C语言中的w,封装了文件接口的标识符:O_WRONLY(写)O_CREAT(不存在就创建文件)O_TRUNC(清空文件),以及权限。

2.5 追加操作

想要把清空变成追加,只需要将open内部的最后一个清空标识符改成追加的标识符:

int fd = open(FILE_NAME, O_WRONLY | O_CREAT | O_APPEND, 0666);

image-20221230135820303

image-20221230135914023

2.6 只读操作

image-20221230142002823

将标识符换成读的标识符

int fd = open(FILE_NAME, O_RDONLY);

image-20221230142901239

image-20221230142927732

这就是以上接口:open/close/write/read,分别对应C语言的fopen/fclose/fwrite/fread,此外对于读还有lseek,对应C语言的fseek。

系统调用接口对应的C语言库函数接口
openfopen
closefclose
writefwrite
readfread
lseekfseek

即库函数接口是封装了系统调用接口的,所有语言的库函数都存在系统调用的影子。

二. 如何理解文件

  • 文件操作的本质:进程和被打开文件的关系

1. 提出问题

进程可以打开多个文件,那是不是意味着系统中一定会存在大量的被打开的文件,被打开的文件要不要被操作系统管理起来呢?答案是一定的。

那么OS如何管理呢? 先描述,再组织。因此操作系统为了管理对应的打开文件,必定要为文件创建对应的内核数据结构标识文件:struct file{}(包含了文件的大部分属性) 因此将结构体链式链接,通过找到链表的首地址从而实现对链表内容的增删查改。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bWf5y5V3-1672976248071)(https://newcfy.oss-cn-beijing.aliyuncs.com/img2/202212301502773.png)]

同时创建多个文件并打印其返回值:image-20221230150313839

  1. 为什么从3开始,0、1、2呢?
  2. 连续的小整数->数组->数组下标

在回答这个问题之前,我们需要了解三个标准的输入输出流:stdin,stdout,stderr!image-20221230155229717

FILE* fp = fopen();

这个FILE实际上是一个结构体,而对于上面的三个输入输出流,实际上也是FILE的结构体:image-20221230154742432

对于这个结构体必有一个字段–>文件描述符,下面就看一下这个文件描述符的值是什么:

2. 文件描述符fd

  • 通过对open函数的学习,我们知道了文件描述符就是一个小整数,即open的返回值

image-20221230155319378

image-20221230155352155

因此这也就解释了为什么文件描述符默认是从3开始的,因为0,1,2默认被占用。我们的C语言的这批接口封装了系统的默认调用接口。同时C语言的FILE结构体也封装了系统的文件描述符。

那为什么是0,1,2,3,4,5……呢?下面就来解释:

image-20221230162410916

PCB中包含一个files指针,他指向一个属于进程和文件对应关系的一个结构体:struct files_struct,而这个结构体里面包含了一个数组叫做struct file* fd _array[]的指针数组,因此如图前三个0、1、2被键盘和显示器调用,这也就是为什么之后的文件描述符是从3开始的,然后将文件的地址填入到三号文件描述符里,此时三号文件描述符就指向这个新打开的文件了。image-20221230163724682

再把3号描述符通过系统调用给用户返回就得到了一个数字叫做3,所以在一个进程访问文件时,需要传入3,通过系统调用找到对应的文件描述符表,从而通过存储的地址找到对应的文件,文件找到了,就可以对文件进行操作了。因此文件描述符的本质就是数组下标。

而现在知道,文件描述符就是从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的下标。所以,只要拿着文件描述符,就可以找到对应的文件

三. 文件fd的分配规则

直接看代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
    int fd = open("myfile", O_RDONLY);
    if(fd < 0){
        perror("open");
        return 1;
    }
    printf("fd: %d\n", fd);
    close(fd);
    return 0;
}

输出发现是 fd: 3

关闭0或2,再看

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
    close(0);
    //close(2);
    int fd = open("myfile", O_RDONLY);
    if(fd < 0){
        perror("open");
        return 1;
    }
    printf("fd: %d\n", fd);
    close(fd);
    return 0;
}

发现是结果是: fd: 0 或者 fd 2

image-20221231152042742

因此,我们知道了,文件fd的分配规则就是将这个array数组从小到大,按照循序寻找最小的且没有被占用的fd,这就是fd的分配规则。

四. 重定向

1. 什么是重定向

对于上面的例子,我们关闭了文件描述符0和2对应的文件吗,那么如果关闭1呢?

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{
    close(1);
    int fd = open("myfile", O_WRONLY|O_CREAT, 00644);
    if(fd < 0){
        perror("open");
        return 1;
    }
    printf("fd: %d\n", fd);
    fprintf(stdout, "fd :%d\n", fd);//与上面打印是一样的功能
    close(fd);
    return 0;
}

根据上面讲到的文件描述符的分配规则,这段代码我们按照顺序进行解释:

首先关闭文件描述符1所对应的stdout(标准输出:输出到显示器),然后通过f分配,这个文件的fd会从小到大扫描发现1的位置没有被使用,于是就会将这个新创建的文件myfile与对应的指针进行连接:image-20221231154736917因此当我们的printf以及fprintf打印到stdout时,由于上层的文件描述符stdout对应的还是1,就会在内核中找到array[1]中对应的文件进行操作,但此时1对应的已经不是标准输出到显示器,而是myfile文件,因此我们在打印时也就不会在显示器中看到fd的值,而是在myfile文件中。image-20221231155443733

那我们来看看是不是这样:

image-20221231155857166

image-20221231155839148

在log.txt没有打印是由于缓冲区的问题,在fprintf的下面加上:fflush(stdout);再看看:image-20221231160122512

即当所有现象都符合我们的预期时,这种现象就是重定向。

  • 重定向的本质:上层用的fd不变,在内核中更改fd对应的struct file*的地址。

常见的重定向有:>(输入), >>(追加), <(输出)。

2. dup2 系统调用的重定向

在上面演示的无论是分配规则还是重定向,直接以close关闭的操作非常的挫,因为这样的close操作不够灵活,所以现在介绍一个系统调用的重定向接口:dup2

int dup2(int oldfd, int newfd);//newfd的内容最终会被oldfd指向的内容覆盖
  • dup2的返回值也就是fd的文件描述符,失败返回-1

那就来演示一下刚才的功能:打印到文件里

image-20221231163747573

image-20221231163901728

可以发现,这样操作简化了刚才的操作,另外,fd的值也不会被改变。

输出重定向演示完了,那我们就可以实现我们刚才提到的三个重定向剩下的追加、输入重定向了。

1. 追加重定向

image-20221231171131944

image-20221231171312635

2. 输入重定向

image-20221231171734365

image-20221231171815552

上面是从键盘中读取,如果不想从键盘读,我们可以重定向到向指定文件中读取:image-20221231172224498

image-20221231172253325

3. 理解:>、>>、<

在之前的学习中,我们模拟过shell部分功能的实现,在这里为了理解这三个常见的重定向,用shell模拟实现这三个重定向:代码链接:lesson18/myshell/myshell.c · 每天都要进步呀/Linux - 码云 - 开源中国 (gitee.com)

此外,这几个常见的重定向的使用方法:文章链接

  • 注:文件是共享的,不会因为进程不同而权限不同,因为文件是磁盘上的,与进程之间是独立的。即当子进程被创建并且发生写时拷贝时,原来的文件并不会再次被拷贝一次。

五. 如何理解Linux一切皆文件

一张图描述:

image-20230104143409800

即我们利用虚拟文件系统就可以摒弃掉底层设备之间的差别,统一使用文件接口的方式进行文件操作。

image-20230104145148510

文件的引用计数:(1条消息) Linux文件引用计数的逻辑_sherlock-wang的博客-CSDN博客

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

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

相关文章

Java 空指针异常的若干解决方案

Java 中任何对象都有可能为空&#xff0c;当我们调用空对象的方法时就会抛出 NullPointerException 空指针异常&#xff0c;这是一种非常常见的错误类型。我们可以使用若干种方法来避免产生这类异常&#xff0c;使得我们的代码更为健壮。本文将列举这些解决方案&#xff0c;包括…

实验十六 BGP协议基本配置

实验十六 BGP协议基本配置边界网关协议BGP(Border Gateway Protocol)是一种实现自治系统AS(Autonomous System) 之间的路由可达&#xff0c;并选择最佳路由的距离矢量路由协议。 自治系统AS (Autonomous System) AS是指在一个实体管辖下的拥有相同选路策略的IP网络。BGP网络中的…

Vue3 实现验证码倒计时

前言 倒计时的运用场景&#xff1a;获取手机验证码倒计时、获取邮箱验证码倒计时等场景&#xff0c;废话不多说&#xff0c;开始吧。 实现效果 实现代码 html&#xff08;重要部分&#xff09; <template><el-button v-if"!sms.disabled" color"#f…

通达信l2接口如何用?

在股票量化投资领域中&#xff0c;通达信l2接口如何用的知识也是要知道和了解的&#xff0c;像现在特别多的团队已经开发有多种不一样的数据接口系统&#xff0c;主要是方便大家去查询行情的时候&#xff0c;能够很快的从这些l2数据接口中产生数据&#xff0c;直观的显示数据的…

酷早报:2023年1月6日全球Web3加密行业重大资讯大汇总

2023年1月6日 星期五 【数据指标】 加密货币总市值&#xff1a;$0.82万亿 BTC市值占比&#xff1a;39.42% 恐慌贪婪指数&#xff1a;26 恐慌【今日快讯】 1、【政讯】 1.1.1、国际货币基金组织IMF&#xff1a;美国通胀尚未“转危为安” 美联储需加息到底 1.1.2、美联储布拉德&a…

Servlet是什么?有哪些优点?

Servlet是使用Java语言编写的运行在服务器端的程序。狭义的Servlet是指Java语言实现的一个接口&#xff0c;广义的Servlet是指任何实现了这个Servlet接口的类&#xff0c;一般情况下&#xff0c;人们将Servlet理解为后者。Servlet主要用于处理客户端传来的HTTP请求&#xff0c;…

【数组经典题目】总结篇

【数组经典题目】总结篇1 二分法2 双指针法3 滑动窗口4 模拟行为5 总结1 二分法 【数组】leetcode704.二分查找(C/C/Java/Js) 使用暴力解法&#xff0c;通过这道题目&#xff0c;如果追求更优的算法&#xff0c;建议试一试用二分法&#xff0c;来解决这道题目 暴力解法时间复…

机器学习实战教程(十):提升分类器性能利器-AdaBoost

一、前言前面的文章已经介绍了五种不同的分类器&#xff0c;它们各有优缺点。我们可以很自然地将不同的分类器组合起来&#xff0c;而这种组合结果则被成为集成方法(ensemble method)或者元算法(meta-algorithm)。使用集成方法时会有多种形式&#xff1a;可以是不同算法的集成&…

CCF BDCI|算能赛题决赛选手说明论文-02

周伟伟 智能边缘事业部&算法工程师 天翼云科技有限公司 中国-广州 zhouweiweichinatelecom.cn黄宇生智能边缘事业部&算法工程师 天翼云科技有限公司 中国-广州 huangyushchinatelecom.cn林瑞玉智能边缘事业部&算法工程师 天翼云科技有限公司 中国-广州 lin…

适合编程初学者的开源项目:小游戏2048(Flutter版)

目标 为编程初学者打造入门学习项目&#xff0c;使用各种主流编程语言来实现。 2048游戏规则 一共16个单元格&#xff0c;初始时由2或者4构成。 1、手指向一个方向滑动&#xff0c;所有格子会向那个方向运动。 2、相同数字的两个格子&#xff0c;相遇时数字会相加。 3、每次…

【库函数】-了解回调函数,并且手把手带你学习qsort函数!!还不知道的赶快进来看看

&#x1f387;作者&#xff1a;小树苗渴望变成参天大树 &#x1f389;作者宣言&#xff1a;认真写好每一篇博客 &#x1f38a;作者gitee:link 如 果 你 喜 欢 作 者 的 文 章 &#xff0c;就 给 作 者 点 点 关 注 吧&#xff01; qsort&#x1f9e8; 前言✨一、什么是回调函数…

报表生成器FastReport.Net常见问题解答来了 | 联合厂商作答

FastReport .Net是一款全功能的Windows Forms、ASP.NET和MVC报表分析解决方案&#xff0c;使用FastReport .NET可以创建独立于应用程序的.NET报表&#xff0c;同时FastReport .Net支持中文、英语等14种语言&#xff0c;可以让你的产品保证真正的国际性。FastReport.NET官方版下…

智云通CRM:如何应对来自竞争对手的阻力?

当销售表明来意后&#xff0c;竞争性客户最常见的回答往往是&#xff1a;“我们和现在的供应商合作得很好。”销售应当牢记&#xff0c;此时我们的目标不是将竞争对手取而代之&#xff0c;而是要努力成为其配角&#xff0c;找机会发现竞争对手能力不足的方面。鉴于此&#xff0…

2023年春节跨年烟花网页特效

粉丝朋友们大家好&#xff0c;我是你们的 csdn的博主&#xff1a;lqj_本人 哔哩哔哩&#xff1a;小淼前端 另外&#xff0c;大家也可以关注我的哔哩哔哩账号&#xff0c;我会不定时的发布一些有关于全栈云开发以及前端开发的详解视频源码 1.微信小程序腾讯云开发之学生端收集数…

搭建VMware ESXi6.7(带图解)

目录 VMware ESXi介绍 准备文件 安装过程 VMware ESXi介绍 VMware ESXi是什么系统&#xff1f; VMware ESXi是可直接安装在物理服务器上的强大的裸机管理系统&#xff0c;不需安装其他操作系统&#xff0c;是VMware服务器虚拟化的基础。通过直接访问并控制底层资源&#x…

操作系统从入门到入土(一)之计算机系统概述

文章目录操作系统的基本概念1.概念2.功能和目标3.特征操作系统的发展操作系统运行环境1.处理器运行环境2.中断和异常3.系统调用系统结构操作系统的基本概念 1.概念 操作系统&#xff08;Operating System&#xff0c; OS&#xff09;是指控制和管理整个计算机系统的硬件和软件…

【C语言】字符串练习,压缩字符串,提取奇偶位(每日小细节015)

前言&#xff1a; 欢迎打开这篇博客&#xff0c;从今天开始&#xff0c;每天和大家分享一个C语言小细节&#xff0c;不久之后还会追加C 一些常常被忽视的小细节和思想统一的编程题目是这个专栏的核心哦 虽然简单但千万别在细节处失分&#xff01;&#xff01;&#xff01;&…

《高效能人士的七个习惯》

专注做有意义的事情。《高效能人士的七个习惯》作者史蒂芬科维&#xff0c;这是一本难得的好书&#xff0c;如果你没有的读过&#xff0c;我推荐你一定要读一下。最近在豆瓣看到一句话说&#xff1a;一定要读经典书籍&#xff0c;因为我们在生活中很难遇到伟大的人物&#xff0…

V2V网络灵敏度分析(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 灵敏度分析是研究与分析一个系统&#xff08;或模型&#xff09;的状态或输出变化对系统参数或周围条件变化的敏感程度的方法。…

Axure绘制登录功能

上一篇文章为大家介绍了一下登录功能的设计思路和相关的流程图&#xff0c;本篇主要带大家从0到1绘制一下B端产品的登录功能如何实现 一、功能解析 本篇主要是针对内部员工使用的B端产品&#xff0c;主要功能如下&#xff1a; ①手机号密码登录 ②忘记密码 ③记住密码 第…