linux的文件系统,理解一切皆文件

这篇具有很好参考价值的文章主要介绍了linux的文件系统,理解一切皆文件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 系统文件I/O

1.1 open

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
pathname: 要打开或创建的目标文件
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。

参数:
 O_RDONLY: 只读打开
 O_WRONLY: 只写打开
 O_RDWR : 读,写打开
 这三个常量,必须指定一个且只能指定一个
 O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
 O_APPEND: 追加写

返回值:
 成功:新打开的文件描述符
 失败:-1

open 函数具体使用哪个,和具体应用场景相关,如目标文件不存在,需要open创建,则第三个参数表示创建文件 的默认权限,否则,使用两个参数的open。

1.2 系统调用 和 库函数

fopen fclose fread fwrite 都是C标准库当中的函数,我们称之为库函数(libc)。

open close read write lseek 都属于系统提供的接口,称之为系统调用接口。

所以,可以认为,f#系列的函数,都是对系统调用的封装,方便二次开发。

1.3 文件描述符(fd)

0 & 1 & 2

  • Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2.
  • 0,1,2对应的物理设备一般是:键盘,显示器,显示器。

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端

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

输入输出还可以采用如下方式: 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{
 char buf[1024];
 int ret = read(0, buf, sizeof(buf));
 if(s > 0){
 buf[s] = 0;
 write(1, buf, strlen(buf));
 write(2, buf, strlen(buf));
 }
 return 0;
}

文件描述符(fd)的分配规则

文件描述符的分配规则:在files_struct数组当中,找到当前没有被使用的 最小的一个下标,作为新的文件描述符。

关闭文件描述符打开的对应的文件

close(fd)

重定向

常见的重定向有:>, >>, <

使用 dup2 系统调用
#include <unistd.h>
int dup2(int oldfd, int newfd);
在myshell中添加重定向功能

原理:

printf是C库当中的IO函数,一般往 stdout 中输出,但是stdout底层访问文件的时候,找的还是fd:1, 但此时,fd:1 下标所表示内容,已经变成了myfile的地址,不再是显示器文件的地址,所以,输出的任何消息都会往文件中写 入,进而完成输出重定向。

FILE

因为IO相关函数与系统调用接口对应,并且库函数封装系统调用,所以本质上,访问文件都是通过fd访 问的。 所以C库当中的FILE结构体内部,必定封装了fd。

#include <stdio.h>
#include <string.h>
int main()
{
 const char *msg0="hello printf\n";
 const char *msg1="hello fwrite\n";
 const char *msg2="hello write\n";
 printf("%s", msg0);
 fwrite(msg1, strlen(msg0), 1, stdout);
 write(1, msg2, strlen(msg2));
 fork();
 return 0;
}

我们发现 printf 和 fwrite (库函数)都输出了2次,而 write 只输出了一次(系统调用)。为什么呢?肯定和 fork有关!

  • 一般C库函数写入文件时是全缓冲的,而写入显示器是行缓冲。
  • printf fwrite 库函数会自带缓冲区(进度条例子就可以说明),当发生重定向到普通文件时,数据 的缓冲方式由行缓冲变成了全缓冲。
  • 而我们放在缓冲区中的数据,就不会被立即刷新,甚至fork之后 但是进程退出之后,会统一刷新,写入文件当中。
  • 但是fork的时候,父子数据会发生写时拷贝,所以当你父进程准备刷新的时候,子进程也就有了同样的 一份数据,随即产生两份数据。
  • write 没有变化,说明没有所谓的缓冲。

所以,printf fwrite 库函数会自带缓冲区,而 write 系统调用没有带缓冲区。另外,我们这里所说的缓冲区, 都是用户级缓冲区。其实为了提升整机性能,OS也会提供相关内核级缓冲区,。 那这个缓冲区谁提供呢? printf fwrite 是库函数, write 是系统调用,库函数在系统调用的“上层”, 是对系统 调用的“封装”,但是 write 没有缓冲区,而 printf fwrite 有,足以说明,该缓冲区是二次加上的,又因为是 C,所以由C标准库提供。

2.文件系统

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端

ls -l读取存储在磁盘上的文件信息,然后显示出来

文件元数据:

  • 模式
  • 硬链接数
  • 文件所有者
  • 大小
  • 最后修改时间

stat命令可以看到更多信息

acm:

  • Access 最后访问时间
  • Modify 文件内容最后修改时间
  • Change 属性最后修改时间

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端

Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区被 划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设 定block大小为1024、2048或4096字节。而上图中启动块(Boot Block)的大小是确定的

  • Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。政府管理各区的例子
  • 超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了
  • GDT,Group Descriptor Table:块组描述符,描述块组属性信息,有兴趣的同学可以在了解一下
  • 块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用
  • inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。
  • i节点表:存放文件属性 如 文件大小,所有者,最近修改时间等
  • 数据区:存放文件内容

创建一个新文件主要有一下4个操作:

1. 存储属性 
内核先找到一个空闲的i节点(这里是263466)。内核把文件信息记录到其中。
2. 存储数据 
该文件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第一块数据
复制到300,下一块复制到500,以此类推。
3. 记录分配情况
文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。
4. 添加文件名到目录

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端

新的文件名hello。linux如何在当前的目录中记录这个文件?内核将入口(131074,hello)添加到目录文件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。

软硬链接:

硬链接(hard link)

我们可以将它理解为一个“指向原始文件inode的指针”,系统不为它分配独立的inode和文件。所以,硬链接文件与原始文件其实是同一个文件,只不过是不同的名字而已。我们每添加一个硬链接,该文件的inode链接数就会增加1;而且只有当该文件的inode连接数为0时,才算彻底将它删除。换言之,由于硬链接实际上是指向原文件的inode的指针,因此即便原始文件被删除,依然可以通过硬链接文件来访问。

总结:

  • 1.硬链接,以文件副本的形式存在。但不占用实际空间。
  • 2.不允许给目录创建硬链接
  • 3.硬链接只有在同一个文件系统中才能创建

软连接(也称为符号链接[symbolic link])

软链接仅仅包含所链接文件的路径名,因此能链接目录文件,也可以跨越文件系统进行链接。但是,当原始文件被删除后,链接文件也将失效,从这一点上来说与Windows系统中的“快捷方式”具有一样的性质。

总结:

  • 1.软链接,以路径的形式存在。类似于Windows操作系统中的快捷方式
  • 2.软链接可以跨文件系统 ,硬链接不可以
  • 3.软链接可以对一个不存在的文件名进行链接
  • 4.软链接可以对目录进行链接

ln 命令

ln 命令用于创建链接文件,格式为“ln [选项] 目标”,其可用的参数以及作用如下:
 

-b 删除,覆盖以前建立的链接

-d 允许超级用户制作目录的硬链接

-f 强制执行

-i 交互模式,文件存在则提示用户是否覆盖

-n 把符号链接视为一般目录

-s 软链接(符号链接)

-v 显示详细的处理过程

 软链接数

将软链接的源文件移除到其他地方,那么软链接将会失效 

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端

软链接支持套娃

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端 

硬链接数

硬链接在删除原始文件后,它的链接文件还可以继续访问,这是因为新建的硬链接不再依赖原始文件的名称等信息,我们可以看到在创建完硬链接后,原始文件的硬盘链接数量增加到了4,如果想要彻底删除,链接数成0才算彻底删除。

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端

可以给软链接增加“硬”链接 这样增加会使软链接数+1

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端 

理解软硬链接

真正找到磁盘上文件的并不是文件名,而是inode。 其实在linux中可以让多个文件名对应于同一个 inode。硬链接就是使用同一个inode!!!

硬链接是通过inode引用另外一个文件,软链接是通过名字引用另外一个文件

linux的文件系统,理解一切皆文件,linux操作系统,linux,java,前端文章来源地址https://www.toymoban.com/news/detail-689206.html

到了这里,关于linux的文件系统,理解一切皆文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】冯诺伊曼体系结构|操作系统概念理解

    个人主页:🍝在肯德基吃麻辣烫 我的gitee:Linux仓库 个人专栏:Linux专栏 分享一句喜欢的话:热烈的火焰,冰封在最沉默的火山深处 本文进入Linux较为晦涩的概念——冯诺依曼体系结构和操作系统的理解。 冯诺依曼体系结构是我们日常计算机都遵守的一个整体架构,计算机

    2024年02月14日
    浏览(57)
  • 【Linux操作系统】深入理解系统调用中的read和write函数

    在操作系统中,系统调用是用户程序与操作系统之间进行交互的重要方式。其中,read和write函数是常用的系统调用函数,用于在用户程序和操作系统之间进行数据的读取和写入。本文将深入介绍read和write函数的工作原理、用法以及示例代码,以帮助读者更好地理解和应用这两

    2024年02月13日
    浏览(42)
  • Linux--进程(一篇博客让你理解操作系统的底层)

    本篇博客讲开始进入进程模块,我们先从冯诺依曼的体系结构和操作系统讲起,由浅入深,先梳理一个Linux相关知识体系框架~   身为一个程序员,我们必须要了解冯诺依曼体系结构,比如我们常见的笔记本电脑,不常见的计算机,如云服务器等,绝大多数都遵循我们的冯诺

    2024年02月05日
    浏览(36)
  • 【Linux深入剖析】冯·诺依曼体系结构以及操作系统的深入理解

    🍁你好,我是 RO-BERRY 📗 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 冯·诺依曼体系结构,也被称为普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的存储

    2024年03月17日
    浏览(46)
  • 【Linux】从软硬件角度重新理解 [ 操作系统与冯诺依曼体系 ](8)

    ​ 前言 大家好吖,欢迎来到 YY 滴 Linux系列 ,热烈欢迎! 本章主要内容面向接触过Linux的老铁,从软硬件层面向大家介绍操作系统与冯诺依曼体系, 主要内容含: 欢迎订阅 YY 滴Linux专栏!更多干货持续更新!以下是传送门! 订阅专栏阅读: YY 的《Linux》系列 ❀❀❀❀❀ 【

    2024年02月08日
    浏览(35)
  • Linux下一切皆文件的理解

    目录 一. 回顾上文 Linux底层进程和被打开文件的映射关系图: Linux部分源代码示意图如下:   ​编辑  二.Linux下一切皆文件的核心理解         在前两篇文章中,我论述了Linux系统中关于文件基础IO的一些内容:         1.有关于文件方面的系统调用函数:open、write、r

    2024年02月10日
    浏览(71)
  • Linux文件系统(操作系统的文件管理)

    参考Linux内核源码版本------ linux-2.4.3 操作系统之下,进程是计算机系统 执行计算任务的基本单位 ,进程访问文件执行数据读写之前,操作系统会从外设获取相应的文件信息,在内存中建立 struct file 结构体对象来 描述和管理文件 ,进程借助 struct file 结构体提供的文件信息执行文件

    2024年02月05日
    浏览(51)
  • 简单理解Linux中的一切皆文件

    一款操作系统要管理各种各样不同的硬件,因为硬件的不同所以它们使用的文件系统也不同。但是按道理来说,文件系统的不同对于用户来说可不是一件好事,操作不同的硬件就要使用不同的方法。 但是Linux有一切皆文件。 简单来说,Linux把所有不同的文件系统都抽象成同一

    2024年02月12日
    浏览(42)
  • 【闪击Linux系列P8】从软硬件角度重新理解 [ 操作系统与冯诺依曼体系 ]

    ​ 前言 大家好吖,欢迎来到 YY 滴 Linux系列 ,热烈欢迎! 本章主要内容面向接触过Linux的老铁,从软硬件层面向大家介绍操作系统与冯诺依曼体系, 主要内容含: 欢迎订阅 YY 滴Linux专栏!更多干货持续更新!以下是传送门! 订阅专栏阅读: YY 的《Linux》系列 ❀❀❀❀❀ 【

    2024年02月13日
    浏览(31)
  • Linux操作系统(六):文件系统组件

    参考资料:阿秀的笔记 Linux 「一切皆文件」 不仅 普通的文件和目录 ,就连 块设备、管道、socket 等,也都是统一交给文件系统管理的。 如何唯一标识文件? 索引节点 inode ,记录了文件的元信息,比如 inode 编号、文件大小、访问权限、创建时间、修改时间、数据在磁盘的位

    2024年04月11日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包