Git数据模型笔记

Git object数据是一个有向无环图,即从任何一个commit出发都可以遍历其任何的parent,但绝不会有环。每个commit都指向一个tree,而一个tree则指向了一个或多个tree和(或)blob

Git数据模型如下图所示:

1

以下面目录结构为例:

2

工作目录下包含了两个目录和三个文件。初始化的git数据模型如下:

3

当修改lib/base/base_include.rb这个文件并提交以后,会产生一个新的blob以及相应的新tree。在当前commit打出tag以后,git数据模型如下:

4

修改根目录下init.rb文件提交后的git数据模型:

5

可以看到,每次commit都会产生一个新的tree
最后的git数据模型如下图所示,包含了16个不可改变的object

6

 

 

参考资料:
Git internals

Lua笔记(22)—— error和assert

Lua中的error函数定义:

error (message [, level])

打印出message后,会终止程序运行。关于level的含义,参考下面例子理解会更清楚(test.lua):

function f0()
        error("Error!")
end

function f1()
        f0()
end

function f2()
        f1()
end

f2()

执行如下:

lua: test.lua:2: Error!
stack traceback:
        [C]: in function 'error'
        test.lua:2: in function 'f0'
        test.lua:6: in function 'f1'
        test.lua:10: in function 'f2'
        test.lua:13: in main chunk
        [C]: in ?

默认情况下,level值为1。“lua: test.lua:2: Error!”把错误位置指向了脚本的第2行。把f0函数修改一下:

function f0()
        error("Error!")
end

再次执行,输出如下:

lua: test.lua:6: Error!
stack traceback:
        [C]: in function 'error'
        test.lua:2: in function 'f0'
        test.lua:6: in function 'f1'
        test.lua:10: in function 'f2'
        test.lua:13: in main chunk
        [C]: in ?

这次错误位置指向了脚本的第6行(“lua: test.lua:6: Error!”),也就是f1()函数,可以看到level指定了发生错误时,应该输出函数调用栈的哪一级函数。

assert函数定义如下:

assert (v [, message])

v是假(nilfalse)时,调用error函数,否则返回所有所有参数。其中message默认值是"assertion failed!"。举例如下:

function f0()
        assert(nil, "Assert!")
end
f0()

输出如下:

lua: test.lua:2: Assert!
stack traceback:
        [C]: in function 'assert'
        test.lua:2: in function 'f0'
        test.lua:13: in main chunk
        [C]: in ?

Lua笔记(21)—— “require module”的等价形式

Learn Lua in 15 Minutes中提到,require module的等价形式:

-- Another file can use mod.lua's functionality:
local mod = require('mod')  -- Run the file mod.lua.

-- require is the standard way to include modules.
-- require acts like:     (if not cached; see below)
local mod = (function ()
  <contents of mod.lua>
end)()
-- It's like mod.lua is a function body, so that
-- locals inside mod.lua are invisible outside it.

这个解释很好地说明了require module的原理,让人豁然开朗。

DMA Remapping —— Domain

Domain是平台上一个抽象的隔离环境,并且被分配了一块主机物理内存。I/O设备作为domain的指定设备(assigned device),可以访问分配给domain的内存。在虚拟化环境下,每个虚拟机都会被当做一个独立的domain

I/O设备分配到指定的domain,并只能访问指定domain所拥有的物理资源。依赖于具体的软件模型,DMA请求的地址可以是虚拟机,也就是domainGuest-Physical AddressGPA),或是由PASID指定进程定义的application Virtual AddressVA),或是由软件定义的抽象的I/O virtual addressIOVA)。不管哪种情况,DMA Remapping硬件都是把相应的地址翻译成Host-Physical AddressHPA)。

什么是KVM?

KVMKernel-based Virtual Machine)是LinuxX86平台提供的完整虚拟化(virtualization) 解决方案,这个方案包括了虚拟化扩展(Intel VTAMD-V)。KVM提供了一个包含虚拟化核心功能可加载的内核模块:kvm.ko,另外还有和处理器相关的模块:kvm-intel.kokvm-amd.ko

利用KVM,你可以创建多个运行LinuxWindows的虚拟机,每个虚拟机都有自己私有的虚拟硬件:网卡,磁盘,等等。

KVM用户空间的组件被包含进入了QEMU的主线。

参考资料:
Kernel Virtual Machine

Lua笔记(20)—— 编译

loadfiledofile都会从文件中加载chunkloadfile只编译这段chunk,并且把编译好的chunk以函数的形式返回,但不运行,而dofile会运行这段chunk。此外,出现错误时,dofileraise error,而loadfile会返回错误代码dofile的代码类似这样:

function dofile (filename)
    local f = assert(loadfile(filename))
    return f()
end

load函数(Lua 5.1使用loadstring)与loadfile类似,只不过load是从字符串中加载chunk,而不是从文件中。需要注意的是,load加载的是chunk,也就是语句,不是表达式。如果要求表达式值的话,需要在前面加上return,这样就得到一个返回表达式值的语句。

Lua会把任何独立的chunk作为一个有变参参数的匿名函数的函数体。举个例子:load('a=1')返回等价于下面的表达式:

function (...) a = 1 end
 

Lua笔记(19)—— 表达式(expression)和语句(statement)

Lua中的表达式(expression)定义:

Expressions denote values. Expressions in Lua include the numeric constants and string literals, variables, unary and binary operations, and function calls. Expressions include also the unconventional function definitions and table constructors.

表达式产生值,包括:数字常量,字符串,变量,单目和双目运算,另外还有函数调用。此外,表达式还包括函数定义和创建table

Lua中的语句(statement)定义:

Lua supports an almost conventional set of statements, similar to those in C or Pascal. The conventional statements include assignment, control structures, and procedure calls. Lua also supports some not so conventional statements, such as multiple assignments and local variable declarations.

语句包括:赋值,控制结构,过程调用(block),多重赋值和local变量定义。

Go语言实践技巧(8)——channel类型

声明channel时,<-表明方向:

chan T          // 能收发`T`类型变量
chan<- float64  // 只能发送 float64 类型变量 (write-only)
<-chan int      // 只能接收 int 类型变量 (read-only)

<-同最左边的channel结合:

chan<- chan int    // 同 chan<- (chan int)
chan<- <-chan int  // 同 chan<- (<-chan int)
<-chan <-chan int  // 同 <-chan (<-chan int)

参考资料:
How to understand “<-chan” in declaration?

Lua笔记(18)—— 解释器的交互模式

Lua自带解释器(Lua.c编译生成的可执行文件)的交互模式会把每一单独的输入行看做是一个chunk,除非这一行不是完整的命令,例如:

> function test()
>> print("test")
>> end

>>标示这一行和之前的行属于同一行。

因此,如果在一行输入local i = 1Lua就会运行这个chunk。再另起一行输入新命令以后,相当于一个新的chunk,前一行的local变量是不可见的。举例如下:

> local i = 10
> print(i)
nil

解决这个问题可以使用do-end将这个代码包成一个chunk

> do
>> local i = 10
>> print(i)
>> end
10

Lua笔记(17)—— 什么是chunk?

Pil中,chunk的定义:

Each piece of code that Lua executes, such as a file or a single line in interactive mode, is called a chunk. A chunk is simply a sequence of commands (or statements).

Lua执行的一段代码,无论是一个Lua文件,或者仅仅是一条语句,均统称为chunk。说白了,chunk就是一段语句(statement)。