chroot 使用笔记

看了下最近很火很高大上的 Docker,比较好奇底层的实现机制,发现主要依赖 Linux Container(LXC) 和 cgroup,于是又了解了下 LXC,在看的过程中看到和 chroot 的比较,突然一些零散的片段在我脑海里迅速串起来……

一直在用 Debian 6,由于不爽 GNOME 3 所以没有升级,不过内核和 GCC 倒是在追新。传说 Debian 8 要使用 XFCE 作为默认桌面,小小期待一下。虽然不是什么狂热的追新族,但是在夜深人静的时候也会悄悄把源切到 unstable 然后 upgrade 看看有哪些自己喜欢的工具升级了。不过 unstable 的依赖关系经常处于不完整状态,有时安装一个包 apt-get 解析出来的关系能把整个系统都删掉,所以也有过几次搞坏系统的经历;而且重装了之后一些特定版本的软件又找不回来了,所以在有升级冲动的时候都会先对根分区备份一下(我的系统只有根目录和家目录)放到家目录里,万一搞坏了可以迅速恢复,而且备份之后的系统还可以作为镜像复制到其它机器上(中间就有过一次换电脑的经历,把旧的系统完整复制过来了)。

好吧,顺便记录一下系统备份和恢复的过程。首先用 U 盘或光盘装个 Live 系统(我用的是 SystemRescueCd ),备份的时候用启动盘启动,把硬盘上的根分区挂载到一个目录上然后在该目录下执行 tar(tar 在解压的时候会还原打包时的相对路径);恢复是同样的步骤,只是把打包变成解压。恢复的时候很多情况下 GRUB …

阅读全文…

使用 C 编写 Lua 模块

Lua 作为一种小巧的语言,一般都是嵌入到 C/C++ 中作为扩展语言,但是也可以作为独立的脚本语言使用,并且可以使用 C/C++ 编写扩展模块。在参考资料 [1] 中有怎样用 C/C++ 编写模块的介绍,但是比较零散,也不是很详细,所以在这里整理一下。

这里使用的 Lua 版本是 5.2.3,系统是 Debian 7。

Hello, world!

不废话,还是先看一下经典的 “Hello, world!” 例子。

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

static int l_hello(lua_State* l)
{
    printf("Hello, world!\n");
    return 0;
}

static const 

阅读全文…

使用 Lua 扩展你的程序 (1)

Lua(参考资料[1])是巴西里约热内卢天主教大学的一个研究小组于 1993 年开发的。小组主要由 Roberto Ierusalimschy, Waldemar Celes 和 Luiz Henrique de Figueiredo 组成,最开始的原型为了处理数据而开发的一种脚本语言,后来逐渐演变成现在的样子。Lua 虽然小巧,但是也包含分支循环结构,动态类型,闭包等特性,有兴趣的可以看看参考资料[2]。只用 Lua 提供的原生 C API 写出来的程序和汇编差不多,需要精确控制栈的内容。为了解放程序员,网上有一些封装好了的 Lua 库,用起来也很方便。

这里主要记录自己使用 Lua 对程序进行扩展的一些尝试,用到相关的 Lua 特性时会展开介绍一下。特别说一下,虽然主要使用 Lua 作为配置文件的语言,但是用其它的语言(Python, Perl, Ruby, …)也可以达到同样的效果,只要程序能够解析所使用的语言,甚至 XML 也可以用来实现后文提到的一些功能,不过前提是你的解析器要支持 XML 来定义分支和循环等功能 :)

简单的 key/value 配置文件

需要配置参数取值的一个常见例子是数据源问题。例如程序需要从一个文件获取运行时需要的数据,测试和正式发布所使用的数据不一样,为了验证程序的正确性也准备了多套不同的数据。为了方便测试,程序使用了一个配置文件 …

阅读全文…

关于 so 的一些笔记

现在的程序越来越复杂,由多个模块构成,如果把所有的模块和依赖都编译到一个单一的可执行文件中,不仅文件体积很大,而且也不利于模块更新;而且有些基础模块可以被多个程序共用,没必要各个程序都打包一份,因此就有了动态链接库。顾名思义,动态链接库就是可以动态地进行链接,在程序需要的时候才会进行加载,并且这份代码在内存里是共享的,在 Windows 中叫“Dynamic Link Library”,后缀是 dll,Linux 上叫“Shared Object”,后缀一般是“so”。

Hello, world!

下面是经典的打印“Hello, world!”的例子:

#ifndef __HELLO_H__
#define __HELLO_H__

void print(void);

#endif
/* hello.c */

#include <stdio.h>

void print(void)
{
    printf("Hello, world!\n");
}
/* main.c */

#include "hello.h"

int main(void)
{
    print();

    return 

阅读全文…

sicp 笔记 (10)

第四章习题 4.1 – 4.15 的解答。从本章开始使用 mit-scheme 9.1.1。

E-4.1: 题目的意思是,函数 list-of-values 对参数列表的求值顺序依赖于解析器的实现。如果解析器对参数列表的求值顺序是从右往左的,那么 list-of-values 的求值顺序也是从右往左的,也就是说,对于 list-of-values 中的“(cons …)”,会先算“(list-of-values (rest-operands …))”这部分,后算“(eval (first-operand …))”,也就是从右往左了;如果解析器的求值顺序是从左往右,那么 list-of-values 的求值顺序也是从左往右。

(define (list-of-values-lr exps env) ; evaluates from left to right
  (if (no-operands? exps)
    '()
    (let ((first-value (eval (first-operand 

阅读全文…

sicp 笔记 (9)

第三章习题 3.73 – 3.82 的解答。

E-3.73:

(load "../examples/3.5.2-infinite-streams.scm")

(define (integral integrand initial-value dt)
  (define int
    (cons-stream initial-value
                 (add-streams (scale-stream integrand dt)
                              int)))
  int)

(define (RC resistance capacitance time-step)
  (lambda (currents initial-voltage)
    (cons-stream initial-voltage
                 (add-streams (scale-stream currents resistance)
                              (integral (scale-stream currents 

阅读全文…

使用 inotify 监控目录和文件的状态

概述

很多时候程序需要对文件状态进行监控,例如在命令行中删掉一个文件,图形界面中的文件管理器也要把这个文件去掉(如果文件管理器正在显示被删除文件所在的目录);如果试图用 vim 保存一个文件,而该文件在修改的时候被其它程序修改过,那么 vim 会给出警告说文件已经发生改变。如果需要对文件状态进行实时监控,一个方法是保存文件的状态,然后不停地扫描目录或文件,如果和上一次保存的状态不一致则发出信号,但是这样的做法效率很低。最好的做法是能够向系统注册一个回调函数,当我们需要监控的目录或文件发生改变时调用回调函数,这样程序就能马上得到通知。

根据参考资料 [1],inotify 之前的文件状态监控机制是 dnotify。dnotify 中的“d”指的是目录,只能监控目录事件的变化,即在该目录下的创建/删除文件引起的事件,但是却不能监控文件本身状态的改变(如读写/访问文件),如果需要实现这样的功能需要应用程序自己比较文件状态。

在 2.6.13 的时候引入的 inotify 提供了比 dnotify 更强大的功能,除了目录还可以对文件状态进行监控。并且它不像 dnotify,每监控一个目录/文件都需要打开一个文件描述符,因此不会影响移动介质的 unmount。从接口形式和功能上看,inotify 和 epoll 很像,只是两者监控的事件类型不一样。

09 年出现了 fanotify(参考资料 [2]),据说是 inotify 的下一代,不过目前来看功能还不如 inotify。

对目录的监控

作为 inotify 的第一个示例,程序会在 /tmp/abc 被创建/删除/移动时打印相应的信息:

#include <stdio.h>
#include <string.h>

阅读全文…

Thrift 学习笔记 (2)

Google 开发的 Protobuf 会经常被拿来和 Thrift 比较,不过 Protobuf 主要提供序列化/反序列化的功能,而 Thrift 还提供了几个 server 模型,加上可以自动生成代码,大大简化了 RPC 的开发。

TSimpleServer

上一篇笔记 的 echo server 为例,一个使用 TSimpleServer 的服务端如下:

// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to 

阅读全文…