第四章习题 4.38 - 4.79 的解答。由于 amb 环境没实现,程序没跑起来,跳过了 4.3 小节的部分题目。
E-4.38: 去掉题目的条件后有5种可能性,分别是:
baker = 1, cooper = 2, fletcher = 4, miller = 3, smith = 5 阅读全文…
baker = 1, cooper = 2, fletcher = 4, miller = 5, smith = …
第四章习题 4.38 - 4.79 的解答。由于 amb 环境没实现,程序没跑起来,跳过了 4.3 小节的部分题目。
E-4.38: 去掉题目的条件后有5种可能性,分别是:
baker = 1, cooper = 2, fletcher = 4, miller = 3, smith = 5 阅读全文…
baker = 1, cooper = 2, fletcher = 4, miller = 5, smith = …
Lua 作为一种小巧的语言,一般都是嵌入到 C/C++ 中作为扩展语言,但是也可以作为独立的脚本语言使用,并且可以使用 C/C++ 编写扩展模块。在参考资料 [1] 中有怎样用 C/C++ 编写模块的介绍,但是比较零散,也不是很详细,所以在这里整理一下。
这里使用的 Lua 版本是 5.2.3,系统是 Debian 7。
不废话,还是先看一下经典的 "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
… 阅读全文…
第四章习题 4.16 - 4.37 的解答。
E-4.16:
(a) 如果匹配到相应的变量再检查一下变量值是否为“unassigned”。
(define (lookup-variable-value var env)
(define (env-loop env)
(define (scan vars vals)
(cond ((null? vars)
(env-loop (enclosing-environment env)))
((eq? var (car vars))
(let ((v (car vals)))
(if (eq? v '*unassigned*)
(error
… 阅读全文…
现在的程序越来越复杂,由多个模块构成,如果把所有的模块和依赖都编译到一个单一的可执行文件中,不仅文件体积很大,而且也不利于模块更新;而且有些基础模块可以被多个程序共用,没必要各个程序都打包一份,因此就有了动态链接库。顾名思义,动态链接库就是可以动态地进行链接,在程序需要的时候才会进行加载,并且这份代码在内存里是共享的,在 Windows 中叫“Dynamic Link Library”,后缀是 dll,Linux 上叫“Shared Object”,后缀一般是“so”。
下面是经典的打印“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
… 阅读全文…
第四章习题 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
… 阅读全文…
第三章习题 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
… 阅读全文…
很多时候程序需要对文件状态进行监控,例如在命令行中删掉一个文件,图形界面中的文件管理器也要把这个文件去掉(如果文件管理器正在显示被删除文件所在的目录);如果试图用 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>
… 阅读全文…
第三章习题 3.38 - 3.72 的解答。
E-3.38:
(a) 每个人的操作都作为一个原子操作的话,有 A(3, 3) 共 6 种可能:
Peter Paul Mary: 90 70 35 阅读全文…
Peter Mary Paul: 90 45 25
Paul Peter Mary: 80 70 35
Paul Mary Peter: 80 40 20
Mary Peter Paul: …
Thrift 是 Facebook 开发的一个二进制通信协议,现在托管在 Apache 基金会。它使用一种自定义的接口描述语言描述使用的数据结构和接口,通过编译可以生成各种语言的接口,如 c++,python,php 等。由于支持生成多种语言,Thrift 可以作为多种语言之间的通信接口,更详细的介绍见参考资料 [1]。
这里使用的 Thrift版本是 0.8.0。
首先编写对应的数据结构和接口描述文件:
namespace cpp Test
service EchoServer {
string echo(1: string msg);
}
使用下面的命令生成对应的 c++ 接口文件:
thrift --gen cpp echoapi.thrift
默认会生成一个“gen-cpp”的文件夹,里面包含下列文件:
echoapi_constants.cpp echoapi_constants.h echoapi_types.cpp echoapi_types.h EchoServer.cpp
… 阅读全文…