programming in lua (8)

第 26 章。

扩展 lua 的一个基本方法是使用 c 语言编写可供 lua 使用的函数。

当我们说 lua“调用”c 函数时,其实并不是真正地调用 c 函数,而是 c 函数遵循一定的约定从 lua 中获取参数并且把结果返回给 lua,或许叫“使用”更合适。在 lua 调用 c 函数前需要先注册 c 函数,即把 c 函数的地址传递给 lua。事实上,lua 使用 c 函数也是通过类似的栈机制,为了避免取了错误的返回值,c 函数需要返回它返回给 lua 的返回值个数(也就是说 lua 应该从栈里取几个值)。

和在 c 中使用 …

阅读全文…

evince 更改文档背景颜色

先说一下用的是 debian 6,evince 版本是 2.30.3。

去年在 evince 的邮件列表中问过这个问题,得到的回答是人手不够,并且这个功能不是太紧急,因此目前并不考虑实现。随着看 pdf 的时间越来越长,白色背景看着实在很不爽,但是又不懂 gtk 编程,因此想通过修改反色的行为来实现修改背景颜色的功能,即当选择了反色的时候并不是把背景和字体的颜色都反过来,而是把背景颜色修改为我喜欢的颜色,字体的颜色不变。

先到源里把代码下下来,grep 一下关键字“invert”加上人肉筛选加上 gdb 打断点后发现实现反色的功能在 libdocument/ev-document-misc.c:

void
ev_document_misc_invert_surface (cairo_surface_t *surface) {
#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1, 9, 2)
    cairo_t *cr;

    cr = cairo_create (surface);

    /* white + DIFFERENCE -> invert 

阅读全文…

linux 文件系统之 vfs (1)

unix 有一句口号“一切都是文件”,说的是普通文件,外设甚至网络都可以当成一个文件来看待:从磁盘上的文件中读取数据,从鼠标/键盘等外设获得输入,接收网络信息等就是从“文件”中读取数据;把数据保存到文件,将文字显示在屏幕上,播放音乐和电影,发送网络信息等可以认为向“文件”写入数据。这个高度统一的接口为操作提供了巨大的便利,用户不需知道实际的对象是什么,只使用系统提供的 read/write 接口就能完成几乎所有的 IO 操作。

既然所有的设备都能被抽象成文件并且用统一的接口进行操作,而且个人觉得在操作系统的几个组成部分(内存管理,进程调度等)中文件系统是相对简单的部分,从这个统一的接口开始了解其内部工作机制或许是个不错的选择。

虚拟文件系统(Virtual Filesystem Switch)

早在 1985 年 SUN 发表了一篇论文(参考资料 [1]),提出了一个用于 Sun OS 的文件系统接口。论文开头说明了设计的目的:

  • 将与文件系统实现相关的部分和与实现无关的部分分开,两者之间由一个经过良好设计的接口连接;
  • 这些接口需要支持 unix 文件系统的操作原语(如创建/删除文件和目录等操作),并且支持各种各样的文件系统;
  • 接口要满足远程文件系统对于 client 的请求操作(例如一些连接/断开的操作,对应于 open/close);
  • 接口提供的操作都是原子性的,锁操作留给具体实现。

整个接口所在的位置和提供的功能如下:

                            +--------------+
                            | System Calls |
                            +--------------+
                                   |
                            +--------------+
                            | Vnode Layer  

阅读全文…

以前写的一个玩具文件系统

这是大三小学期的时候做的,不知不觉快 3 年了,转过来留个纪念。

发信人: Xer (小x|SL小分队), 信区: Linux
标  题: [分享][操作系统小学期]模拟文件系统
发信站: 北邮人论坛 (Sat Sep  5 21:41:41 2009), 站内

============
写在前面的话
============

这个程序是我的操作系统小学期做的文件管理部分,磁盘布局是抄minix的,但是内存数据结构是自己想的(越往下写越感觉自己设计的不对)。从8月24号到熄灯前的那段时间基本是每天晚上2点上床7点起床,其它时间除了吃饭上厕所基本就是在查资料写代码,整个疯狂的程序员。既然抄了GPL的东西,就遵循GPL的规定开源了。

数据结构跟vfs的出入挺大,所以写出来的东西不是很好,大牛们轻拍~

====
简介
====

文件系统用一个文件模拟,默认大小是32M(由ofs.h中的OFS_SIZE定义),默认块大小为4K(由ofs.h中的PAGE_SIZE定义)。程序由ANSI C写成,可以在Windows和Linux上运行。

模拟文件系统总共分六大部分,分别是引导块(MBR),超级块(super block),索引节点位图(inode bitmap),数据块位图(data block bitmap),索引节点表(inode table)和数据区(data area)。各个部分的大致情况如下图所示:

+-------------+
|     MBR     | 

阅读全文…

programming in lua (7)

第 25 章。

lua 的一个重要的应用是作为程序配置文件的语言(configuration language)。下面通过一些例子循序渐进地说明其应用。

一个简单的例子

假设一个 c 语言程序要画一个窗口界面,窗口的长和宽可以由用户指定。要实现这个功能还有另外更简单的方法,例如使用环境变量或只包含 (key, value) 形式的普通文本文件,但是如果使用普通文本文件你还是需要对其进行解析。程序的配置文件如下:

-- conf.lua
-- define window size
width = 200
height = 300

下面的程序演示了怎样使用 lua 提供的接口来获得这两个变量的值:

#include <stdio.h>

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

int main(void)
{
    lua_State* 

阅读全文…

c 语言实现封装,继承和多态

封装

c 语言使用的 struct 没有访问控制,任何程序都能访问 struct 的成员。为了隐藏 struct 里的成员名称和位置,可以将具体的 struct 定义放在 .c 文件中,而在头文件中增加一个指向该结构体的指针。因为无法得知指针类型的具体定义,对这个私有结构体成员的访问只能通过提供的 set() 和 get() 函数。

下面是头文件 test.h 的定义:

#ifndef __TEST_H__
#define __TEST_H__

struct test {
    struct _test* t;
};

int test_constructor(struct test*);
int test_get(struct test*);
void test_set(struct test*, 

阅读全文…

programming in lua (6)

中断了的 lua 学习再次回来了……之前学完基本语法后就不想看接下来的标准库讲解了,因为看了不用基本等于白看,没几天就忘了;但是不看的话连 lua 有什么功能都不知道,更不用说知道把 lua 用在什么地方。最近想学习用 lua 来扩展程序,因此又捡起来了,不过跳过了书中的 part II 和 part III,这里是第 24 章。顺便说一下,这里使用的 lua 版本也从 5.1.4 升到 5.2.0,不过区别应该不大。

lua 是一个嵌入式语言,就是说它不是一个单独的程序,而是一套可以在其它语言中使用的库,在前面使用过的 lua 交互程序其实是利用 lua 提供的库所实现的一个解析器。lua 可以作为 c 语言的扩展,反过来也可以用 c 语言编写模块来扩展 lua,这两种情况都使用同样的 api 进行交互。lua 与 c 主要是通过一个虚拟的“栈”来交换数据。

简单的 lua


阅读全文…

项目总结 (1)

年前开始做这个项目,虽然主要的功能放假前已经完成,但是老板为了体现实验室的主题——并行计算,要求把一个简单的 hash 查找功能弄成复杂的“多线程并行计算”,尽管最后的多线程实现比串行的还慢(通过使用 gprof 分析发现花在同步上的开销超过了多线程带来的并行效益,因为实际的 hash 查找不怎么耗时间)。当然这些我是无力改变的,不过有个好处就是老板虽然不懂具体技术,但是却不会瞎指挥,所以在实现上倒是挺自由的,因此可以随便尝试自己想学的东西,只要最后项目完成就行。

好了,发完牢骚之后总结一下从中学到的东西吧。

生产者-消费者问题

我觉得所有的问题基本都可以归结为生产者-消费者问题:输入是生产者,程序处理是消费者。刚开始写的是串行的代码,使用惯用的套路:

int main(void)
{
    ......

    while ((rec = producer()))
        consumer(rec);

    ......
}

串行程序需要由 main() 函数驱动,主要逻辑由 main() 函数搭建,这样的话如果非要把多线程嵌到这个模型中,看起来会有点奇怪:

void* producer(void)
{
    /* blcok until data arrives */
    return get_resource_from(resource_pool);
}

void consumer(void* 

阅读全文…

vim 配置整理

为了补偿前几周对 vim 的不忠,这两天整理了一下 vim 的配置,贴上来备份一下,也算是一篇凑数的文章。

目前正在使用的插件有 neocomplcache(自动补全),bufexplorer(多个 buffer 间切换),code_complete(代码模板),nerdtree(文件浏览的侧边栏),nerdcommenter(注释的好帮手)。另外还有一些好用的插件如 taglist(代码结构浏览,只需装上 ctags 即可,不需生成 tags 文件),echofunc(输入函数左括号时显示函数原型)等。

最后贴一下配置文件,是在 deb 包配置文件的基础上修改的(2013.12.09 更新):

" Uncomment the next line to make Vim more Vi-compatible
" NOTE: debian.vim sets 'nocompatible'.  Setting 'compatible' changes numerous
" options, so 

阅读全文…

交换 ctrl 和 caps lock

因为 ctrl 键在笔记本键盘的左下角,对于经常使用 ctrl 键的人来说是个痛苦的事情。在网上搜了下有几种交换键位的方法,在这里记录一下。

第一种方法是使用 xmodmap(参考资料 [1])。建立一个新文件 ~/.Xmodmap,添加以下内容:

remove Lock = Caps_Lock
remove Control = Control_L
keysym Control_L = Caps_Lock
keysym Caps_Lock = Control_L
add Lock = Caps_Lock
add Control = Control_L

然后执行

xmodmap ~/.Xmodmap 2>/dev/null

就行了。如果不想每次启动都手动输入命令,可以把命令写到 ~/.xinitrc 中。注意如果把命令写到 …

阅读全文…