使用 fuse 编写文件系统 (2)

读写文件

在第一个程序的基础上增加读写 hello-world 的功能:

#define FUSE_USE_VERSION 26

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

#define BUFFSIZE 8192

static int content_size;
static char content[BUFFSIZE];
static const char* fname = "hello-world";

static int ou_readdir(const char* path, void* buf, fuse_fill_dir_t filler,
                      off_t 

阅读全文…

使用 fuse 编写文件系统 (1)

FUSE 的全称是“Filesystem in Userspace”,即“用户空间的文件系统”,这是一个内核模块,能够让用户在用户空间实现文件系统并且挂载到某个目录,就像在内核实现的文件系统一样。使用 FUSE 有几个好处:一是因为在用户空间实现,开发和调试都比较方便;二是可以把一些常用的服务以文件系统的形式展现,方便操作,如 ftpfs,sshfs,mailfs 等;另外可以避免一些版权问题,如 Linux 上对 ntfs,zfs 的操作都是通过 FUSE 实现的。当然用户空间的实现也有缺点,最明显的就是由多次在用户态/内核态切换带来的性能下降。

根据参考资料 [1] 的介绍,用户通过 FUSE 和内核的通信过程如下:

                   +----------------+
                   | myfs /tmp/fuse |
                   +----------------+
                          |   ^
+--------------+          v   |
| ls /tmp/fuse |    +--------------+
+--------------+    |    libfuse   |
      ^  

阅读全文…

programming in lua (12)

第 9 章和第 30 章部分内容,都是讲线程相关的。

基本概念

lua 中的 coroutine 和我们通常说的“线程”概念相近,但是这里的 coroutine 并不是真正的线程,在某个时刻只有一个 coroutine 在执行。lua 将 coroutine 的所有函数都放在一个叫“coroutine”的 table 中,下面来看一下这些函数。

co = coroutine.create(function () print("hello") end)
print(co) -- thread: 0x11fa810
print(coroutine.status(co)) -- suspended
coroutine.resume(co) -- hello
print(coroutine.status(co)) -- dead

create() 接收一个函数作为参数,创建一个对应的 …

阅读全文…

programming in lua (11)

第 29 章和 31 章。这两章都是讲资源管理的,就放一起看了。

userdata 可能是用户自己分配的一段内存(内存里可能有一个域是文件描述符,可能是一个指向另外一段内存的指针,等等),当这段 userdata 被释放时,其中包含的其它资源也需要被释放(如需要关闭文件,释放另一段内存等)。某些语言提供了一种叫做“finalizer”的机制来完成这件事,在 lua 中对应的是一个 __gc 的域,当某个 userdata 被 lua 回收时,如果它对应的 metatable 中有 __gc 这个域,则这个域所指向的函数(通常指向的是函数)将会被调用,这样用户就能释放和 userdata 相关联的内容。

目录遍历迭代器

第 26 章实现过一个目录遍历的程序,程序每次返回一个包含所有目录项的 table。这里我们将要实现一个迭代器,每次只返回一个目录:

for dname in dir(".") do
    print(dname)
end

c 语言中遍历目录的步骤:首先使用 opendir() 函数打开目录返回一个指向 DIR …

阅读全文…

programming in lua (10)

第 28 章。这章主要是讲怎样在 lua 中使用 c 语言中自定义的数据结构。

先看一个简单的例子:boolean 数组。在 lua 中可以使用 table 来存储,在 c 语言中由于每个变量只占一个 bit,使用的内存只占用 table 实现的 3%。

程序使用如下的数据结构和相关的宏定义:

#include <limits.h>

#define BITS_PER_WORD (CHAR_BIT*sizeof(unsigned int))
#define I_WORD(i)     ((unsigned int)(i) / BITS_PER_WORD)
#define I_BIT(i)      (1 << ((unsigned int)(i) % BITS_PER_WORD))


阅读全文…

sicp 笔记 (1)

“sicp”全称是“Structure and Interpretation of Computer Programs”,是 MIT 计算机专业第一年的一门入门课程的教材(据说现在已经取消了这门课,取而代之的是另一门使用 python 的课程)。网上很多人都强烈推荐这本书,给出了各种赞美之词,因此从网上找了个排版比较好的电子版(google 搜“sicp unofficial texinfo format”,我用的是 2.neilvandyke4 这个版本)。直到研究生快毕业才开始学习别人本科第一年的教材,希望亡羊补牢还不算晚。

这里使用 plt-scheme,除了 1.28 小题的 random 函数之外其它题目都能运行,推荐使用 mit-scheme(debian 中只有 i386 的包,64 位的需要自己到官网下载编译)。

下面是第一章的习题解答部分。

E-1.1: 把内容对着敲一遍就行了

E-1.2:

(/ (+ 5 4 (- 2 (- 3 (+ 

阅读全文…

pthread 学习笔记 (4)

自旋锁

除了前面提到过的互斥锁和读写锁外,还有另外一种锁:自旋锁(spinlock)。自旋锁的原理比较简单,就是当某个资源不可用时不断查询,直到资源可用:

void tese_and_set(bool* condition)
{
    bool tmp = *condition;
    *condition = true;
    return tmp;
}

void func()
{
    while (test_and_set(&condition));

    /* visit */

    condition = false;
}

其中的操作 test_and_set() 可以看成一个原子操作,通常由硬件来实现。如果 condition 为 false,while 循环会不断地查询 condition 的状态,直到其可用为止。因为在条件不满足时程序也一直在忙,这样会消耗 cpu 资源,所以自旋锁适合用在执行时间不长的临界区中,例如修改一个数值等。

由于自旋锁比较简单,pthread …

阅读全文…

hadoop笔记 (4):streaming

hadoop 提供了 3 种方式来实现自己的功能,一种是 java 接口,另一种是 pipes,还有一种是 streaming。streaming 允许用任何语言来开发 mapper 和 reducer,它们和 hadoop 之间的交互通过标准输入/输出来进行。这种方式的好处是调试很方便。

先来看一个使用 bash 编写的 wordcount 的例子:

#!/bin/bash

while read line; do
    arr=($line)
    let i=0
    while ! [ -z ${arr[$i]} ]; do
        echo -e "${arr[$i]}\t1"
        let i=$i+1
    done

阅读全文…

hadoop笔记 (3):pipes例子分析 (2)

使用 partitioner 和 combiner

下面的程序是对 hadoop 1.0.3 自带例子(src/examples/pipes/impl/wordcount-part.cc)的一个修改版:

#include <string>
#include <vector>
using namespace std;

#include <hadoop/Pipes.hh>
#include <hadoop/StringUtils.hh>
#include <hadoop/TemplateFactory.hh>

class WordCountMapper : public HadoopPipes::Mapper {

    public:

        WordCountMapper(HadoopPipes::TaskContext& context) {}

        void map(HadoopPipes::MapContext& context)
        {
            vector<string> words = HadoopUtils::splitString(context.getInputValue(), " 

阅读全文…

hadoop笔记 (2):pipes例子分析 (1)

Pipes 是 hadoop 提供的 c++ 接口,但是在官网上找不到 pipes 的文档,只能从例子开始一点点摸索。实验环境是 debian 6 amd64,hadoop 1.0.3。hadoop 的安装目录是 $HOME/hadoop,安装和配置过程在上一篇安装笔记中有提到。

为了少敲些字符,给 hadoop 命令做了一个 alias:

alias hadoop='$HOME/hadoop/bin/hadoop'

单词统计程序

下面的程序是对 hadoop 1.0.3 自带的单词统计程序(src/examples/pipes/impl/wordcount-simple.cc)的一个修改版:

#include <string>
#include <vector>
using namespace std;

#include <hadoop/Pipes.hh>
#include <hadoop/StringUtils.hh>
#include <hadoop/TemplateFactory.hh>

class WordCountMapper 

阅读全文…