linux原理和方法 linux系统命令大全分享( 二 )


还会加载一些 vim 插件 source_in_path。使用 load_start_packages 加载 package。
下面这种只是第一个交互了 。等待客户敲下 enter 键:
wait_return(TRUE);
我们总是看见的:“Press ENTER or type command to continue“ 只是在这里执行的 。确认完 。就说明你真的是要打开文件 。并展现到终端了 。
怎么打开文件?怎么展现字符到终端屏幕?
这一切都来自于 create_windows 这种函数 。名字也较好理解 。只是初始化的时候创建终端窗口来着 。
/*
* Create the requested number of windows and edit buffers in them.
* Also does recovery if "recoverymode" set.
*/
create_windows(?ms);
这里其实涉及到两个方面:
把资料读出去 。读到内存;
把字符渲染到终端;
怎么把资料从磁盘上读出去 。只是 IO 。怎么渲染到终端这种我们不管 。这种使用的是 termlib 或者 ncurses 等终端编程库来实现的 。有兴趣的应该了解下 。
这种函数会调用到我们的第一个核心函数:open_buffer。这种函数做两个时间:
create memfile:创建一个 memory + .swp 文件的抽象层 。读写资料都会过这一层;
read file:读原始文件 。并解码(用来展现到屏幕);
函数调用栈:-> readfile
-> open_buffer
-> create_windows
【linux原理和方法 linux系统命令大全分享】-> vim_main2
-> main
真正干活的是 readfile 这种函数 。评论一下 。readfile 是一个 2533 行的函数 。。。。。。
readfile 里面会择机创建 swp 文件(曾经一些话 。应该用来复原资料) 。调用的是 ml_open_file 这种函数 。文件创建好之后 。size 占用 4k 。里面往往一般是一些特殊的元资料(用来复原资料用的) 。
划重要时机:.{文件名}.swp 这种掩藏文件是有格式的 。前 4k 为 header 。后面的内容也是根据一个个block 团队的 。
再往后走 。会调用到 read_eintr 这种函数 。读取资料的内容:
long
read_eintr(int fd, void *buf, size_t bufsize)
{
long ret;
for (;;) {
ret = vim_read(fd, buf, bufsize);
if (ret >= 0 || errno != EINTR)
break;
}
return ret;
}
这是一个最底层的函数 。是系统调用 read 的一个封装 。读出去之后 。这里回答了一个关键问题:vim 的存储原理是啥?
划重要时机:本质上调用 read 。write 。lseek 这样朴素的系统调用 。而已 。
readfile 会把二进制的资料读出去 。之后进行字符转变编码(根据配置的模式) 。编码不对只是乱码喽 。每次都是根据一个特殊 buffer 读资料的 。例如 8192。
划重要时机:readfile 会读完文件 。这只是怎么当 vim 打开一个超大文件的时候 。会超级慢的原因 。
这里提一点题外话:memline 这种封装是文件之上的 。vim 改写文件是改写到内存 buffer。vim 根据策略来 sync memfile 到 swp 文件 。一个是以免丢弃未保存的资料 。第二是为了节省内存 。
mf_write 把内存资料写到文件 。在 .test.txt.swp 中的只是这样的资料结构:

linux原理和方法 linux系统命令大全分享

文章插图
block 0 的 header 主要标识:vim 的版本;
写文件的路径;
字符编码方法;
这里实现提一个重要知识点:swp 文件里存储的是 block 。block 的管理是以一个树形结构进行管理的 。block 有 3 种类别:
block0:头部 4k。往往一般是存储一些文件的元资料 。例如路径 。编码模式 。时间戳等等;
pointer block:树形内部节点;data block:树形叶子节点 。存储客户资料;
2 敲下 :w 背后的原理进程初始化我们讲完了 。现在来看下 :w 触发的调用吧 。客户敲下 :w 命令触发 ex_write 回调(初始化的时候配置好的) 。全部的流程皆在 ex_write。我们来看下这种函数做了什么 。
先撇开代码实现来说 。客户敲下 :w 命令其实只是想保存改写而已 。
那么第一个问题?客户的改写在哪里?在 memline 的封装 。只要没执行过 :w 保存 。那么客户的改写就没改写到原文件上(小心哦 。没保存曾经 。一定没改写原文件哦) 。这时候 。客户的改写可能在内存 。也很有可能在 swp 文件 。存储的资料结构为 block。所以 。:w 其实只是把 memline 里面的资料刷到客户文件而已 。怎么刷?
重要时机步骤如下(以 test.txt 举例):创建一个 backup 文件( test.txt~ ) 。把原文件拷贝出去;
把原文件 test.txt truancate 截断为 0 。等于清空原文件资料;

推荐阅读