当前位置: 首页 > 网络应用技术

Linux Editor VIM的IO存储原理

时间:2023-03-05 18:09:53 网络应用技术

  这并不容易,更干燥的商品,欢迎遵循公共帐户:Qiyun Cloud Storage

  无意间用VIM打开了一个10 g的文件,更改了一条内容,保存了它,放慢了我,花费的时间足以让喝几杯茶,这引起了我的好奇心。VIM到底打开并保存了什么?

  vim被称为编辑的神,以其极其强大的可扩展性和功能而闻名。vi/vim作为标准编辑器几乎在Linux的每个分布中都存在。VIM的学习曲线相对较陡,必须有一个恢复的过程在早期。

  VIM是终端编辑器。今天,为什么VIM如此重要?

  由于某些方案必须是IT,例如在线服务器终端,除了VI/VIM终端编辑器外,您别无选择。

  VIM的历史很长。GitHub有一个文档总结了VIM的历史过程:VIM历史记录,GitHub开源代码:代码仓库。

  作者今天没有谈论VIM。本文在Internet上进行了很多搜索。QI将从VIM存储IO原理的角度分析VIM工件。

  考虑一些小问题。如果读者有兴趣,他们可以继续阅读:

  VIM编辑文件的原理是什么,使用了什么黑色技术?

  VIM打开一个10克的大文件。为什么这么慢,什么?

  VIM修改了10克的大文件。保存后感觉较慢?为什么?

  vim似乎会产生额外的文件?交叉发行,您该怎么办?

  定位:由于VIM的功能太强大,因此根本没有完成。本文重点介绍了IO,并从存储的角度分析了VIM的原理。

  语句和VIM版本如下:

  操作系统版本:Ubuntu 16.04.6 LTS

  VIM版本:VIM -VI Improvd 8.2(2019年12月12日,编辑7月25日2021 08:44:54)

  测试文件名:test.txt

  VIM只是一个二进制程序。阅读器和朋友也可以自己下载,编译,调试它,效果更好。

  通常,VIM编辑文件非常简单。您只需要在VIM之后遵循文件名:

  这将打开文件和编辑。该命令被拆除,通常,我们可以快速看到终端中文件的内容。

  这个过程发生了什么?这到底是什么意思?

  本质是运行一个名为vim的程序,并且参数为test.txt.txt。它与您之前写过的Helloworld程序没有什么不同,但是VIM程序可以与终端人机机器进行交互。

  因此,此过程无非是从开始到(背景周期监视)的过程初始化过程。

  VIM有一个输入文件,该文件在此处定义。首先,操作系统相关的初始化(MCH是机器的缩写):

  mch_early_init();然后,执行,执行分配参数,全局变量的初始化:

  例如,必须将此类参数分配给全局变量,因为将来应经常使用它。

  此外,与命令类似的地图表已静态定义:

  焦点:这样的vim命令实际上对应于定义的c折线函数:.function是数据编写的核心函数。在另一个示例中,对应于退出的回调。

  换句话说,在VIM中类似地支持的情况下,在初始化时实际上确定了命令。人类交互只是输入字符串。在从终端到字符串的VIM进程读取后,找到相应的回调函数并执行它。然后,将初始化一些主目录,当前目录和其他变量。

  配置与终端窗口相关的内容。该部分主要与某些终端库有关:

  然后加载配置文件,例如.vimrc,以使您的VIM唯一。

  一些VIM插件也将加载到加载软件包。

  以下是第一个交互,等待用户敲击Enter键:

  我们经常看到:“按Enter或Type命令继续执行”。确认后,这意味着您确实要打开文件并将其显示给终端。

  如何打开文件?如何将字符显示到终端屏幕上?

  所有这些都来自此功能。名称也被充分理解,即初始化时,创建一个终端窗口。

  实际上,有两个方面:

  阅读数据并阅读内存;

  将角色渲染到终端;

  如何从磁盘中读取数据是IO。如何渲染终端。我们不在乎。这是由终端编程库(例如Termlib或Ncurses)实现的。如果您有兴趣,您可以理解。

  此功能将调用我们的第一个核心函数:,此功能两次进行:

  创建memfile:创建内存 + .swp文件的抽象层。读取数据将通过此层;

  读取文件:读取原始文件并解码(以显示在屏幕上);

  功能调用堆栈:

  此功能确实在起作用。Tucao是2533行的函数。

  它将选择创建SWP文件(如果有以前,可以用于还原数据)。此功能称为。创建文件后,大小占4K,这主要是特定的元数据(用于还原数据)本质

  点:{文件名} .swp此隐藏的文件是正式的。第一个4K是标头,以下内容也由块组织。

  回去,您将调用此功能以阅读数据的内容:

  这是一个底层函数。这是系统调用读取和阅读的软件包。这里回答了一个关键问题:VIM的存储原理是什么?

  要点:本质上是这样一个简单的系统调用。

  将读取二进制数据,然后角色转换编码(根据配置模式)。编码是错误的。每个时间我从固定缓冲区(例如8192)读取数据。

  点:阅读文件后。这就是为什么VIM打开大文件时VIM非常慢的原因。

  这是一些外部故事:此软件包在文件之上。VIM修改文件以修改为内存缓冲区。VIM根据策略将MEMFILE与SWP文件同步。

  将内存数据写入文件。这是.test.txt.swp中的数据结构:

  块0的标题的主要身份:

  vim版本;

  编辑文件的路径;

  字符编码;

  这是一个重要的知识点:SWP文件中的块,块的管理由树结构管理。块有3种类型:

  块0:头部为4K,主要是存储某些文件的元数据,例如路径,编码模式,时间戳等。

  指针块:树状内部节点;

  数据块:树状的叶子节点,存储用户数据;

  该过程是初始化的。让我们完成呼叫。用户敲门命令以触发回调(初始化时配置了配置)。

  所有过程都在那里,让我们看一下此功能的作用。

  撇开代码实施,用户敲门实际上只是想保存他的修正案。

  所以第一个问题?用户的修改在哪里?

  在Memline的封装中,只要没有执行保存,用户的修改就不会修改为原始文件(请注意,在存储之前,必须修改原始文件)。在SWP文件中。存储的数据。结构是块。

  因此,实际上只是在MEMLINE中刷到用户文件中的数据。如何刷新?

  关键步骤如下(例如以Test.txt为例):

  创建一个备份文件()以复制原始文件;

  将原始文件truancate修剪为0,这等同于清除原始文件数据;

  从MEMLINE(内存 +)复制数据,然后重写为原始文件;

  删除备份文件;

  以上是要做的一切,让我们看下面的代码。

  触发回调是核心函数是该功能1987行。

  在此函数中,将创建一个带有名称的背面的备份文件,例如

  获取备份文件的句柄,然后复制数据(即一个周期),每8K操作一次,从复制到备份。

  定位:如果它是一个大文件,这里会很慢。

  备份循环如下:

  我们看到有效的是,这是包装函数,它实际上是系统调用的函数,该功能负责将缓冲区数据写入磁盘文件。

  复制备份文件后,您可以准备原始文件。

  思考:为什么首先需要文件备份?

  离开脱衣舞后,您的恢复错误。这是真正的备份文件。

  修改原始文件之前的第一步,原始文件为0,然后从memline(内存 + SWP)中复制数据,然后写回原始文件。

  点:这是另一个文件副本。当大文件很大时,这里可能会很慢。

  点:VIM没有调用原始文件,例如调用PWRITE/PREAD,但是在清除整个文件后,更新复制方法以更新文件。

  这样,文件已更新,最后您只需要删除备份文件即可。

  这是我们数据编写的完整过程。它并不像您想象的那么简单!

  简单地总结:修改文件并保存呼叫数据时发生了什么?

  人 - 机器互动,触发呼叫恢复功能,in->完整写作;

  特定操作是:首先备份文件(完整副本);

  然后,将原始文件切为0,并从memline(内存 +的最新数据 +包装)复制数据,然后写(所有副本);

  【绘画】

  我之前所说的,我们从数据组织的角度进行了解释。对于用户对文件的修改,VIM将两层抽象封装在原始文件上:文件对应于文件。

  它是什么?

  它对应于文本文件中的每一行。

  基于什么?

  这是虚拟内存空间的实现。vim将整个文本文件映射到内存并单独管理。

  这是典型的虚拟内存实现解决方案。编辑器的修改反映在Memfile的修改中。修改被修改为块。这是一个线性空间。每个块对应于文件的位置。名称,VIM将通过策略从内存替换块,并将其写入SWP文件以保存内存。这是交换文件的来源。

  块区分3种类型:

  块0件:树根,文件元数据;

  指针块:树的分支,指向下一个块;

  数据块:树的叶子,存储用户数据;

  交换文件组织:

  块0是一个特殊的块,该结构占据1024字节内存。该文件根据1页对齐,因此是4096字节。如下所示:

  阻止其他两种类型:

  指针类型:这是中间分支节点,指向块;

  数据类型:这是叶节点;

  #define data_id(('d' << 8) + 'a') // data block id

  #define PTR_ID (('p' << 8) + 't') // pointer block id

  这个 ID 相当于魔数,在 swp 文件中很容易识别出来,比如在下面的文件中第一个 4k 存储的是 block0,第二个 4k 存储的是 pointer 类型的 block。

  第三,第四个 4k 存储的是一个 data 类型的 block ,里面存储了原文件数据。

  当用户修改一行的时候,对应到 memline 的一个 line 的修改,对应到这行 line 在哪个 block 的修改,从而定期的刷到 swap 文件。

  假设原文件名称:test.txt 。

  文件估计很多人都没见过,因为消失的太快了。这个文件在修改原文件之前生成,修改原文件之后删除。作用于只存在于 ,是为了安全备份的。

  划重点:test.txt~ 和 test.txt 本质是一样的,没有其他特定格式,完全是用户数据。

  读者朋友试试 vim 一个 10 G的文件,然后改一行内容, 保存,应该很容易发现这个文件(因为备份和回写时间巨长 )。

  这个文件估计绝大多数人都见过, 文件生命周期存在于整个进程的生命周期,句柄是一直打开的。很多人认为 是备份文件,其实准确来讲并不是备份文件,这是为了实现虚拟内存空间的交换文件, 才是真正的备份文件。

  swp 是 的一部分,前面 4k 为 header 元数据,后面的为 一个个 4k 的数据行封装。和用户数据并不完全对应。

  才是最新的数据。

  没啥,就是用的 , 这样的系统调用来读写数据而已。

  :是真正的备份文件,诞生于修改原文件之前,消失于修改成功之后;

  :swap 文件,由 block 组成,里面可能由用户未保存的修改,等待 这种调用,就会覆盖到原文件;

  一般情况下,你能直观感受到,慢在两个地方:

  vim 打开的时候;

  修改了一行内容, 保存的时候;

  先说第一个场景:vim 一个 10G 的文件,你的直观感受是啥?

  我的直观感受是:命令敲下之后,可以去泡杯茶,等茶凉了一点,差不多就能看到界面了。为什么?

  在进程初始化的时候,初始化窗口之前, -> 里面调用 会把整个文件读一遍(完整的读一遍),在屏幕上展示编码过的字符。

  划重点:初始化的时候, 会把整个文件读一遍。 10 G的文件,你可想而知有多慢。我们可以算一下,按照单盘硬件 100 M/s 的带宽来算,也要 102 秒的时间。

  再说第二个场景:喝了口茶,改了一个单词, 保存一下,妈呀,命令敲下之后,又可以去泡杯茶了?为什么?

  先拷贝出一个 10G 的 备份文件,102 秒就过去了;

  截断为 0,再把 memfile( )拷贝回 ,数据量 10 G,102 秒过去了(第一次可能更慢哦);

  是的,vim 一个 test.txt 10 G 的文件,会存在某个时刻,需要 >= 30 g磁盘空间。

  原始文件test.txt 10 g

  备份文件test.txt?10g

  交换文件.test.txt.swp> 10G

  VIM编辑文件不使用黑魔法,但仍使用简单的系统调用;

  VIM编辑大文件,当打开它时,它非常慢,因为它将完全读取文件(),并且保存时非常慢,因为它将两次读取和写入文件(备份一次,覆盖原始文件一次);

  它是与文件修改相对应的虚拟存储空间的VIM抽象层(实际上由内存块和SWP文件组成),并且存储单元由块组成。保存后,从memfile读取到原始文件;

  它基于另一层包装,将用户的文件抽象成“线”的概念;

  该文件始终是打开的,数据将定期交换以恢复灾难以适应;

  该文件是真实的备份文件。在覆盖原始文件之前,成功介绍原始文件后它消失了。

  VIM基本上是整个文件的处理,而不是本地处理。大型文件的编辑根本不适合VIM。然后,谁将使用vim用vim?vim编辑10 g文件。

  一个函数2533行,1987年的函数。线条代码。essessessenceit并不是我对每个人的热情

  VIM的好奇心使Qi Qi有点源代码,学习了IO知识,并且不想受到成千上万行的功能的教育。理解扣除1,您无法理解珠子。学会了吗?

  这并不容易,更干燥的商品,欢迎遵循公共帐户:Qiyun Cloud Storage