0%

使用 Emacs 大概也有大半年了,越用越觉得它的强大,始终都有惊喜,每次看到一个功能,心中想:Emacs 可以吗?答案真的往往会是 Yes!

1
2
3
4
(defun factorial (n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))

上面这种充满括号的奇怪的语言叫 Lisp,它是仅次于 Fortran 的最老的高级程序设计语言,名称来源于 LISt Processing,它有两个方言,分别是 Common Lisp 和 Scheme。 Emacs lisp (elisp) 来源于 Common Lisp。使用 Emacs,如果不能自己打造适合自己的功能,虽然仍然可以享受 Emacs 带来的流畅和便利,但却会与另一种乐趣失之交臂,这篇文章简要叙述 elisp 的基本概念和语法。

Hello World

1
(message "Hello, World!")
Read more »

C++中,我们熟悉的对象的创建和释放过程如下:

1
2
3
4
5
6
7
8
9
class Thing
{
...
};

...

Thing *pt = new Thing;
delete pt;

代码中 new 完成两部分动作,1. 调用 ::operator new 分配对象所占内存空间,2. 调用 Thing 构造函数初始化对象内容。delete 也完成两部分动作,1. 调用析构函数清除对象内容,2. 调用 ::operator delete 释放内存空间。

STL 将这两部分动作分离了开来,内存分配由 alloc:allocate() 负责,释放由 alloc:deallocate() 负责,对象构造和析构依次由 ::contruct()::destroy() 负责。

具体实现位于 stl_alloc.h, stl_contruct.h, stl_uninitialized.h 中,stl_alloc.h 负责内存分配,stl_contruct.h 负责对象构建和析构,stl_uninitialized.h 提供一系列全局函数来进行内存填充 (fill) 和拷贝 (copy)。其实 alloc 并不符合标准规范,而应该是 allocator,位于 stl_defalloc.h 中。

Read more »

1
2
3
4
5
6
7
template <class Iterator, class T>
Iterator find(Iterator first, Iterator last, const T& value)
{
while (first != last && *first != value)
++first;
return first;
}

上面是 C++ 中一个普通的模板函数,调用的时候直接将特定类型变量当参数传入就行,这段程序运用了 Generic Programming(泛型编程/GP)。

GP 要求函数尽量一般化,假设参数可适用于任何范畴,那么函数 find 到底有多一般化?

输入条件,对于类型 Iterator,首先能够以 operator “*” 来操作提取其指向区域的值,并且可以用 operator “++” 来移至下一个 Iterator 对象…

为了表示输入条件,假定 Iterator 必须是一个 iterator,在这个地方 iterator 没有其他意思,只是我们定义出来的一个概念,用来指定一组描述某个类型的条件。

Read more »

印度官方旅游广告词是 Incredible India!

不管之前怎么看待这个国家,身临其境总是会想起这句话,当然语调的不同可以表述截然相反的感受。

Read more »

Paging

Paging unit 用来将 linear address 转换为 physical address,为了高效,linear address 按照一定的长度被分为若干组,称为 pages,并且,内存也被分为各个定长的 page frame (physical pages),page 和 page frame 的长度是一样的,前者表示一块数据,它可以储存在 page frame 或者硬盘中。

在 paging unit 开始工作之前,kernel 先初始化 page tables,这是一个用来映射 linear address 到 physical address 的表。

Linear address 由三部分组成:

  • Directory,10 bits
  • Table,10 bits
  • Offset,12 bits
Read more »

这一个系列将会详细的介绍 Linux kernel 内存管理机制。

使用特定内存地址就可以访问某一块内存单元,为了实现有效的寻址,操作系统将一系列繁琐的操作隐藏了起来,内存地址按照不同的抽象层次分为如下三种:

  1. Logical address: 标识运算符或者程序指令的地址,由段号 (segment selector) 和偏移量 (offset) 组成。
  2. Linear address: 32位的无符号整型数,可以用来表示最大4GB地址空间。
  3. Physical address:内存物理单元的地址。

CPU 控制单元通过 Segmentation Unit 将 Logical address 转换为 Linear address,而后,再通过 paging unit 将 linear address 转换为 physical address,至此,特定地址的访问行为完成。

Segmentation Unit

Read more »