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


从 memline (内存 + .test.txt.swp)拷贝资料 。从头开始写入原文件 test.txt;
删除备份文件 test.txt~;以上只是 :w 做的全部事件了 。下面我们看下代码 。
触发的回调是 ex_write。核心的函数是 buf_write。这种函数 1987 行 。
在这函数 。会使用 mch_open 创建一个 backup 文件 。名字后面带个 ~。例如 test.txt~。
bfd = mch_open((char *)backup
拿到 backup 文件的句柄 。之后拷贝资料(只是一个循环喽), 每 8K 操作一次 。从 test.txt 拷贝到 test.txt~。以做备份 。
划重要时机:如果是 test.txt 是超大文件 。那这里就慢了哦 。
backup 循环如下:// buf_write
while ((write_info.bw_len = read_eintr(fd, copybuf, WRITEBUFSIZE)) > 0)
{
if (buf_write_bytes(&write_info) == FAIL)
// 如果失败 。则终止
// 否则直到文件结束
}
}
我们观看到的 。干活的是 buf_write_bytes。这是 write_eintr 的封装函数 。其实也只是系统调用 write 的函数 。负责写入一个 buffer 的资料到磁盘文件 。
long write_eintr(int fd, void *buf, size_t bufsize) {
longret = 0;
longwlen;
while (ret < (long)bufsize) {
// 封装的系统调用 write
wlen = vim_write(fd, (char *)buf + ret, bufsize - ret);
if (wlen < 0) {
if (errno != EINTR)
break;
} else
ret += wlen;
}
return ret;
}
backup 文件拷贝完成之后 。就应该准备动原文件了 。
思考:怎么要先文件备份呢?留条后路呀 。搞错了还一些复原 。这种才是真正的备份文件 。
改写原文件曾经的第一步 。ftruncate 原文件到 0 。之后 。从 memline (内存 + swp)中拷贝资料 。写回原文件 。
划重要时机:这里又是一次文件拷贝 。超大文件的时候 。这里可能巨慢哦 。
for (lnum = start; lnum <= end; ++lnum)
{
// 从 memline 中获取资料 。返回一个内存 buffer( memline 其实只是内存和 swap 文件的一个封装)
ptr = ml_get_buf(buf, lnum, FALSE) - 1;
// 将这种内存 buffer 写到原文件
if (buf_write_bytes(&write_info) == FAIL)
{
end = 0;// write error: break loop
break;
}
// ...
}
划重要时机:vim 并不是调用 pwrite/pread 这样的调用来改写原文件 。而是把整个文件清空之后 。copy 的方法来更新文件 。涨知识了 。
这样就完成了文件的更新啦 。末尾只要删掉 backup 文件就可 。
// Remove the backup unless 'backup' option is set or there was a
// conversion error.
mch_remove(backup);
这种只是我们资料写入的完美流程啦 。是不是没有你想的那么无脑!
无脑小结下:当改写了 test.txt 文件 。调用 :w 写入保存资料的时候发生了什么?
人机交互 。:w 触发调用 ex_write 回调函数 。于 do_write -> buf_write 完成写入 ;
详细操作是:先备份一个 test.txt~ 文件出去(全拷贝);
接着 。原文件 test.txt 截断为 0 。从 memline( 即 内存最新资料 + .test.txt.swap 的封装)拷贝资料 。写入 test.txt (全拷贝) ;
资料团队结构曾经讲的太细节 。我们从资料团队的角度来解答下 。vim 针对客户对文件的改写 。在原文件之上 。封装了两层抽象:memline 。memfile。分别对应文件 memline.c。memfile.c。

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

文章插图
先说 memline 是啥?
对应到文本文件中的每一行 。memline 是基于 memfile 的 。
memline 基于 memfile 。那 memfile 又是啥?
这种是一个虚拟内存空间的实现 。vim 把整个文本文件映射到内存中 。通过自己管理的方法 。这里的单位为 block 。memfile 用二叉树的方法管理 block。block 不定长 。block 由 page 组成 。page 为定长 4k 大小 。
这是一个典型虚拟内存的实现方案 。写器的改写都体现为对 memfile 的改写 。改写都是改写到 block 之上 。这是一个线性空间 。每一个 block 对应到文件的要给地点 。有 block number 编号 。vim 通过策略会把 block 从内存中换出 。写入到 swp 文件 。从而节省内存 。这只是 swap 文件的名字由来 。
block 区分 3 种类别:
block 0 块:树的根 。文件元资料;
pointer block:树的分支 。指向下一个 block;
data block:树的叶子节点 。存储客户资料;
swap 文件团队:
linux原理和方法 linux系统命令大全分享

文章插图
block 0 是特别块 。结构体占用 1024 个字节内存 。写到文件是根据 1 个page 对齐的 。所以是 4096 个字节 。