还会加载一些 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
-> 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 中的只是这样的资料结构:
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,等于清空原文件资料;
从 memline (内存 + .test.txt.swp)拷贝资料,从头开始写入原文件 test.txt;
删除备份文件 test.txt~;以上只是 :w 做的全部事件了,下面我们看下代码 。
触发的回调是 ex_write,核心的函数是 buf_write,这种函数 1987 行 。
推荐阅读
- 如何装win10正版系统 win10官方下载地址
- 丽水职业技术学院官网教务管理系统 丽水职业技术学院
- 挂机就可以赚钱的游戏 天天挂机系统日赚150
- 全国交强险查询系统 全国交强险查询网址
- 向往背景音乐系统怎么样 背景音乐系统方案
- 启动数据库命令mysql mysql启动命令是什么
- 谷歌新机型出来了 安卓12系统发布时间
- 上海卓非自动化控制系统有限公司_工商信用信息_经营范围期限状态_法人_地址_注册资本_怎么样
- 怎么删除页眉的那一条线 怎么删除页眉?
- telnet端口不通怎么解决 telnet端口号命令