今天才知道,广为浏览的门槛真低

2009年12月26日 没有评论

以前一直认为,文章啥的,至少要被转载或链接个几百次,访问量至少要达到数万才能算有点影响力吧,怎么也要到10万才能算广为浏览吧。不过今天看到的北京市第一中级人民法院列出的几个数字彻底颠覆了我的看法。人民法院诶,他们给出的可是具有法律效力的关于“广为浏览”的认定哦。

列一下:

  • 文章1:2005年10月4日发表,截至2008年12月23日,被链接5次。
  • 文章2:2006年1月5日发表,截至2008年12月23日,被链接5次,总点击量402次。
  • 文章3:2006年2月26日发表,截至2008年12月23日,被链接5次,总点击量748次
  • 文章4:2006年3月13日发表,截至2008年12月23日,被链接6次,总点击量512次
  • 文章5:2006年5月7日发表,截至2008年12月23日,被链接7次,总点击量57次。
  • 文章6:2007年8月1日发表,截至2008年12月23日,被链接8次,总点击量488次。
  • 文章7:2008年12月9日发表,截至2008年12月12日,被链接33次,总点击量5154次。

就算按照其中最高的要求,鄙博客几篇文章也早就被广为浏览了。

好奇心重的同志们,请自行Google其中提到的数字。

标签:

liboi – 管理基于OpenInkpot的电子书设备的支持库

2009年12月23日 没有评论

自从用了OpenInkpot,并且推荐了几个用v3的朋友换成OpenInkpot之后,越发觉得,对于普通用户来说,管理阅读器相当的麻烦,三天两头就需要提供技术支持,从安装字体到拷贝书籍再到配置系统,不一而足。

因为OpenInkpot在V3上使用USB RNDIS驱动连接阅读器和PC,并且通过SSH的方式连接设备,但是SSH的设置步骤复杂,而且在Vista x64和Win7这种比较新的操作系统上面总有些问题,对用户要求比较高。

其实V3的这种连接模式比较像Windows Mobile手机的方式,这种方式在具有一个客户端的时候有很大的灵活性,例如WM手机的Active Sync。另外就是等待OI支持USB Mass Storage,即模拟一个U盘出来的方式,但是看起来一时半会儿也没有做的计划。

但是OI有它的好处,就是很多可以自定义的东西,例如阅读器的键绑定——我一直想把翰林V3左侧的翻页键互换——但是修改的方式需要用户ssh到阅读器修改。这对于普通用户来说简直就是噩梦。

同时,OI还有一些问题,例如在0.2 rc5当中添加的libextract,即在书架模式下显示书籍的元信息,而不是文件名,在很多时候其实是有问题的。官方的绕过方式是重命名一个文件,但是同样需要ssh到阅读器修改。

由于这些问题,最好有一个可以用来管理电子书设备的客户端软件。这个软件也许可以做下面的事情:

  1. 自动配置电子书的USB RNDIS连接
  2. 书籍搜索、下载和同步
  3. 数据的同步,例如书签
  4. 状态备份和恢复,例如当前阅读的图书的页码,书籍版式(横屏,切白边等)。
  5. 安装字体
  6. 设备软件更新
  7. 设备配置修改,例如修改键绑定
  8. 其他工具性的功能,例如拷屏

等等。

但是前提是要有一个客户端软件。因此最近先整了一个基础库,取名 liboi,即lib-openinkpot之意,host在Google Code上面: http://code.google.com/p/liboi/。经过几个星期的晚上+周末的工作,现在把0.1版本放出来,这个版本支持最简单的功能:

  1. 根据默认的SSH配置连接阅读器。
  2. 获取阅读器信息,类似OpenInkpot版本号
  3. 在阅读器当中执行命令(有了这个功能剩下的就是想象力了)

目前只支持Linux平台,请在项目主页上下载源码包自行编译。源码包当中有oish.c文件,会生成一个oish(OpenInkpot Shell)的程序,可以作为例子程序使用。

后面的事情,主要包括:

  1. 拷贝文件,包括拷进来和拷出来。
  2. Windows Porting
  3. SSH自动配置

另外招募擅长客户端界面的同仁开发客户端GUI,我要做的话估计界面会很丑。当然了,没报酬,代码开源,纯自愿参与。

标签: , ,

简单的愿望

2009年12月21日 1 条评论

今天看到的有关北风的一篇小文章,很有同感: http://news.sina.com.cn/c/2009-09-27/163718738245.shtml

姓名:温云超
年龄:38
职业:自由职业 [...]

3.你希望的生活是什么样的?我可以自由自在说我想说的话,我家人可以过着没有必要顾虑我的前途的生活。

5.对你而言,什么最重要?
我可以说我想说的话,我可以做法律没有禁止我做的事情。

6.你现在的梦想是?
我可以决定我的未来,通过我的选票或是我的劳动。

7.你对中国的未来有何期待?
我以及我的孩子,可以免于恐惧,生活在我及他爱的土地上,享受他们创造的财富,享受他们应有的快乐。

其实我的愿望很简单,对我,我的家人和孩子,我们的心智,身体和寿命,都只被我们自己,而不是我们所吃的、喝的、以及身处的环境限制。我们能够保护我们我们所爱的,我们所相信的,我们所创造的,以及我们所拥有的。我们能够有一个一致合理的准绳去规范我们的行为,而不是在今天受到鼓励,而在明天被禁止。

但是现在,在这片神奇的土地上,越来越收紧的限制,越来越恶化的环境,让这些简单的愿望已经越来越难达到了。

标签:

Python multiprocessing 使用手记[3] – 关于Queue

2009年12月13日 没有评论

继续讨论Python multiprocessing,这次讨论的主要内容是mp库的核心组件之一的Queue。

Queue是mp库当中用来提供多进程对象交换的方式。对象交换和上一部分当中提到的对象共享都是使多个进程访问同一个对象的方式,两者的区别就是,对象共享是多个进程访问同一个对象,对象交换则是将对象从一个进程传输的另一个进程。

multiprocessing当中的Queue使用方式和Python内置的threading.Queue对象很像,它支持一个put操作,将对象放入Queue,也支持一个get操作,将对象从Queue当中读出。和threading.Queue不同的是,mp.Queue默认不支持join()和task_done操作,这两个支持需要使用mp.JoinableQueue对象。

由于Queue对象负责进程之间的对象传输,因此第一个问题就是如何在两个进程之间共享这个Queue对象本身。在上一部分所言的三种共享方式当中,Queue对象只能使用继承(inheritance)的方式共享。这是因为Queue本身基于unix的Pipe对象实现,而Pipe对象的共享需要通过继承。因此,在一个典型的应用实现模型当中,应该是父进程创建Queue,然后创建子进程共享该Queue,由父进程和子进程分别读写。例如下面的这个例子:

import multiprocessing
 
q = multiprocessing.Queue()
 
def reader_proc():
    print q.get()
 
reader = multiprocessing.Process(target=reader_proc)
reader.start()
 
q.put(100)
reader.join()

另一种实现方式是父进程创建Queue,创建多个子进程,有的子进程读Queue,有的子进程写Queue,例如:

import multiprocessing
 
q = multiprocessing.Queue()
 
def writer_proc():
    q.put(100)
 
def reader_proc():
    print q.get()
 
reader = multiprocessing.Process(target=reader_proc)
reader.start()
writer = multiprocessing.Process(target=writer_proc)
writer.start()
 
reader.join()
writer.join()

由于使用继承的方式共享Queue,因此代码当中并没有明显的传输Queue对象本身的代码,看起来似乎只要将multiprocessing当中的对象换成threading当中的对象,程序仍然能够工作。反之,拿到一个现有的多线程程序,是不是将threading改成multiprocessing就可以工作呢?也许可以,但是更可能的情况是你会遇到很多问题。

第一个问题就是mp的Queue需要考虑多进程之间的对象传输,因此所传输的对象必须是可以pickle的。否则,在Queue的put操作上会抛出PicklingError。

其他的一些差异表现在一些技术细节上,这些不是任何高层逻辑可以抽象掉的,不知道这些差异会导致一些潜在的错误,例如死锁。在总结这些潜在的犯错的可能的同时,我们会简单看一下mp当中Queue的实现方式,以便能够方便的理解为什么会有这样的行为。这些实现问题仅仅针对Linux,Windows上面的实现和出现的问题在这里不涉及。

mp.Queue建构在系统的Pipe之上,但是实际上进程并不是直接将对象写入到Pipe里面,而是先写入一个本地的buffer,再由一个专门的feed线程将其放入Pipe当中。读取端则是直接从Pipe当中读出对象。之所以有这样一个feed线程,是为了能够提供Queue接口函数所需要的put的超时控制。但是由于这个feed线程的存在,mp.Queue提供了几个额外的函数来控制它,一个函数close来停止该线程,以及join_thread来join该线程。close同时负责把所有在buffer当中的对象刷新到Pipe当中。

但是这个feed线程也是个麻烦制造者,为了保证所有被放入Queue的东西最终都能够到达另外一端的进程,mp库注册了一个atexit的处理函数,用来在进程退出的时候自动close并且join该feed线程。这个join动作带来了很多问题,比如潜在的死锁。考虑下面一种状况:一个父进程创建了两个子进程,一个子进程读,另一个子进程写。当需要停止这些进程的时候,父进程如果先把读进程结束,但是同时写进程已经将太多的对象写入Queue,导致后继的对象等待在buffer当中,则这个进程将无法终止,因为atexit的处理函数等待把所有buffer当中的对象放入Pipe,但是Pipe已经满了,然后陷入了死锁。

有人可能会问,那只要保证总是按照数据流的顺序来停止进程不就行。问题是在很多复杂的系统流程当中,可能存在一个环形的数据流,这种情况下,无论按照什么顺序停止进程,终究有一个进程可能陷入这种情景当中。

幸运的是,Queue对象还提供了一个成员函数cancel_join_thread,这个函数可以使得在进程停止的时候不进行join操作,这样可以避免死锁,代价就是这个时候尚未刷新到Pipe当中的对象都会丢失。鉴于即使调用了join_thread,残留在Pipe当中的对象仍然可能丢失,所以一旦选择使用mp的Queue对象,就不要假设不会在流程当中丢对象了。

另外一个可能的方案是使用mp库当中的SimpleQueue对象。这个对象在文档当中没有提及,但是在multiprocessing.queue模块当中有定义。这个对象就是去掉了buffer的Queue对象,因此可能能够避免上面说的问题的。但是SimpleQueue没有提供put和get的超时处理,两个动作都是阻塞的。

除了使用multiprocessing.Queue,还可以使用multiprocessing.Pipe进行通信。mp.Pipe是Queue的底层结构,但是没有feed线程和put/get的超时控制。一定程度上和SimpleQueue很像。需要注意的是Pipe带有一个参数 duplex,当设置为True(默认)的时候,Pipe并不是使用系统的pipe来实现,而是通过socketpair,即Unix Domain Socket来实现。这个和pipe相比有些微的性能差异。

另外一个使用Queue的方式不是mp库内置的。这种方式使用上一篇文章当中提到的server process的方式来共享一个Queue对象。这个Queue对象实际上在server process当中,所有的子进程通过socket连接到server process获取该Queue的代理对象进行操作。说到这有人会想起来mp库有一个内置的SyncManager对象,可以通过multiprocess.Manager函数获取到,通过该对象的Queue方法可以获取一个Queue的代理对象。不幸的是,这个方法不是正确的获取Queue的方式,原因正如上一篇文章所说,SyncManager.Queue方法的每次调用获取到的是一个新建对象的代理对象,而不是一个共享对象。正确的使用server process当中的Queue的方式是:

共同部分:

import multiprocessing.managers as mpm
import Queue
 
class SharedQueueManager(mpm.BaseManager): pass
q = Queue.Queue()
SharedQueueManager.register('Queue', lambda: q)

服务进程:

mgr = SharedQueueManager(address=('', 12345))
server = mgr.get_server()
server.serve_forever()

客户进程:

mgr = SharedQueueManager(address=('localhost', 12345))
mgr.connect()
q = mgr.Queue() # 这里q就是共享的Queue对象的代理对象

这种方式比起mp库内置的Queue,有一些性能上的影响,因为毕竟牵涉到多次网络通讯,但是带来的好处是没有feed线程带来的一系列问题,而且理论上不会存在丢数据的问题,除非server process崩溃。但是正如上一篇所说,server process本身就不是很靠谱的,因此这里也只是“理论上”不会丢数据而已。

说到性能,这里就列两个性能数据,以前在twitter上面提到过的(这两个连接无法访问的请联系我):

操作对象为 pickle后512字节的对象,通过proxy操作Queue的性能大约是7000次/秒(本机)或1100次/秒(多机),如果使用 multiprocessing.Queue,效率可达54000次/秒。

向前一步,就是朝鲜

2009年12月12日 3 条评论

先是在Twitter上看到了这则消息,后来追到cnnic的网站上发现,确实有这么一则通知

关于进一步加强域名注册信息审核工作的公告

为了提升域名注册信息的真实性、准确性、完整性,进一步加强域名注册信息审核工作,现通知如下要求:

1、用户向域名注册服务机构在线提交域名注册申请的同时,应当提交书面申请材料。申请材料包括加盖公章的域名注册申请表(原件)、企业营业执照或组织机构代码证(复印件)、注册联系人身份证明(复印件)。

2、域名注册服务机构应当认真审核用户提交的书面申请材料,审核合格后,将书面申请材料通过传真或电子邮件的形式提交至我中心,并保留书面申请资料。

3、自域名提交在线申请之日起5日内我中心未收到书面申请材料的或域名申请材料审核不符合条件的,该域名将予以注销。

4、以上要求自2009年12月14日上午9时起施行。

如有疑问,请致电CNNIC,联系方式为:
7×24小时客服电话:010-58813000
邮件:service@cnnic.cn

中国互联网络信息中心
2009年12月11日

由于申请域名需要提供企业经营执照,这意味着个人用户、个体户等无法继续申请.cn域名。这对于国内互联网的发展,尤其是电子商务的发展是破坏性的。不知道对于国内用户通过国外的域名提供商注册.cn域名的,CNNIC如何进行控制,不排除可能会禁止通过国外的域名提供商注册.cn域名,毕竟CNNIC是.cn域名的管理机构。

另外听说,今天上海的所有机房都禁止论坛接入了,论坛出现一条有害信息,就会被没收服务器,罚款1万。连论坛这种web 1.5时代的用户交互的网站都不允许了,web 2.0的网站,blog,群体智慧的东西,生存的空间就更小了。我们只能眼睁睁看着国外如火如荼的新技术,新模式创新。内容审查制度已经让国内互联网的环境已经极大倒退,也许比美国已经落后了5年,互联网的5年。

从互联网上找到的一张照片,向前一步,就是朝鲜。(credit: darkhorselasa@sohu

前方朝鲜,就差一步 credit: <a mce_href="http://pp.sohu.com/photoview-290580025-22539525.html" href="http://pp.sohu.com/photoview-290580025-22539525.html">darkhorselasa@sohu</a><br>

向前一步,就是朝鲜 credit: darkhorselasa@sohu

论坛出现一条有害信息,就会被没收服务器,罚款1万
标签:

Python multiprocessing 使用手记[2] – 跨进程对象共享

2009年12月7日 没有评论

继续写关于Python multiprocessing的使用手记,继上次的进程模型之后,这次展开讨论一下multiprocessing当中的跨进程对象共享的问题。

在mp库当中,跨进程对象共享有三种方式,第一种仅适用于原生机器类型,即python.ctypes当中的类型,这种在mp库的文档当中称为shared memory方式,即通过共享内存共享对象;另外一种称之为server process,即有一个服务器进程负责维护所有的对象,而其他进程连接到该进程,通过代理对象操作服务器进程当中的对象;最后一种在mp文档当中没有单独提出,但是在其中多次提到,而且是mp库当中最重要的一种共享方式,称为inheritance,即继承,对象在父进程当中创建,然后在父进程是通过multiprocessing.Process创建子进程之后,子进程自动继承了父进程当中的对象,并且子进程对这些对象的操作都是反映到了同一个对象。

这三者共享方式各有特色,在这里进行一些简单的比较。

首先是共享方式所应对的对象类型,看这个表:

共享方式 支持的类型
Shared memory ctypes当中的类型,通过RawValue,RawArray等包装类提供
Inheritance 系统内核对象,以及基于这些对象实现的对象。包括Pipe, Queue, JoinableQueue, 同步对象(Semaphore, Lock, RLock, Condition, Event等等)
Server process 所有对象,可能需要自己手工提供代理对象(Proxy)

这个表总结了三种不同的共享方式所支持的类型,下面一个个展开讨论。

其中最单纯简单的就是shared memory这种方式,只有ctypes当中的数据类型可以通过这种方式共享。由于mp库本身缺少命名的机制,即在一个进程当中创建的对象,无法在另外一个进程当中通过名字来引用,因此,这种共享方式依赖于继承,对象应该由父进程创建,然后由子进程引用。关于这种机制的例子,可以参见Python文档当中的例子 Synchronization types like locks, conditions and queues,参考其中的test_sharedvalues函数。

然后是继承方式。首先关于继承方式需要有说明,继承本质上并不是一种对象共享的机制,对象共享只是其副作用。子进程从父进程继承来的对象并不一定是共享的。继承本质上是父进程fork出的子进程自动继承父进程的内存状态和对象描述符。因此,实际上子进程复制了一份父进程的对象,只不过,当这个对象包装了一些系统内核对象的描述符的时候,拷贝这个对象(及其包装的描述符)实现了对象的共享。因此,在上面的表当中,只有系统内核对象,和基于这些对象实现的对象,才能够通过继承来共享。通过继承共享的对象在linux平台上没有任何限制,但是在Windows上面由于没有fork的实现,因此有一些额外的限制条件,因此,在Windows上面,继承方式是几乎无法用的。

最后就是Server Process这种方式。这种方式可以支持的类型比另外两种都多,因为其模型是这样的:

server process模型

server process模型

在这个模型当中,有一个manager进程,负责管理实际的对象。真正的对象也是在manager进程的内存空间当中。所有需要访问该对象的进程都需要先连接到该管理进程,然后获取到对象的一个代理对象(Proxy object),通常情况下,这个代理对象提供了实际对象的公共函数的代理,将函数参数进行pickle,然后通过连接传送到管理进程当中,管理进程将参数unpickle之后,转发给相应的实际对象的函数,返回值(或者异常)同样经过管理进程pickle之后,通过连接传回到客户进程,再由proxy对象进行unpickle,返回给调用者或者抛出异常。

很明显,这个模型是一个典型的RPC(远程过程调用)的模型。因为每个客户进程实际上都是在访问manager进程当中的对象,因此完全可以通过这个实现对象共享。

manager和proxy之间的连接可以是基于socket的网络连接,也可以是unix pipe。如果是使用基于socket的连接方式,在使用proxy之前,需要调用manager对象的connect函数与远程的manager进程建立连接。由于manager进程会打开端口接收该连接,因此必要的身份验证是需要的,否则任何人都可以连上manager弄乱你的共享对象。mp库通过authkey的方式来进行身份验证。

在实现当中,manager进程通过multiprocessing.Manager类或者BaseManager的子类实现。BaseManager提供了函数register注册一个函数来获取共享对象的proxy。这个函数会被客户进程调用,然后在manager进程当中执行。这个函数可以返回一个共享的对象(对所有的调用返回同一个对象),或者可以为每一个调用创建一个新的对象,通过前者就可以实现多个进程共享一个对象。关于这个的用法可以参考Python文档当中的例子“Demonstration of how to create and use customized managers and proxies”。

典型的导出一个共享对象的代码是:

ObjectType object_
class ObjectManager(multiprocessing.managers.BaseManager): pass
ObjectManager.register("object", lambda: object_)

注意上面介绍proxy对象的时候,我提到的“公共函数”四个字。每个proxy对象只会导出实际对象的公共函数。这里面有两个含义,一个是“公共”,即所有非下划线开头的成员,另一个是“函数”,即所有callable的成员。这就带来一些限制,一是无法导出属性,二是无法导出一些公共的特殊函数,例如__get__, __next__等等。对于这个mp库有一套处理,即自定义proxy对象。首先是BaseManager的register可以提供一个proxy_type作为第三个参数,这个参数指定了哪些成员需要被导出。详细的使用方法可以参见文档当中的第一个例子。

另外manager还有一些细节的问题需要注意。由于Proxy对象不是线程安全的,因此如果需要在一个多线程程序当中使用proxy,mp库会为每个线程创建一个proxy对象,而每个proxy对象都会对server process创建一个连接,而manager那边对于每个连接都创建一个单独的线程来为其服务。这样带来的问题就是,如果客户进程有很多线程,很容易会导致manager进程的fd数目达到ulimit的限制,即使没有达到限制,也会因为manager进程当中有太多线程而严重影响manager的性能。解决方案可以是一个进程内cache,只有一个单独的线程可以创建proxy对象访问共享对象,其余线程只能访问该进程当中的cache。

一旦manager因为达到ulimit限制或者其他异常,manager会直接退出,遗憾的是,这时候已经建立的proxy会试图重新连接manager – 但是它已经不存在了。这个会导致客户进程hang在对proxy的函数调用上,这个时候,目前除了杀掉进程没有找到别的办法。

另外proxy使用socket的方式比较tricky,因此和内置的socket库有很多冲突,比如socket.setdefaulttimeout(Python Issue 6056 )。在setdefaulttimeout调用了之后,进程当中所有通过socket模块建立的socket都是被设置为unblock模式的,但是mp库并不知道这一点,而且它总是假设socket都是block模式的,于是,一旦调用了setdefaulttimeout,所有对于proxy的函数调用都会抛出OSError,错误代码为11,错误原因是非常有误导性的“Resource temporarily unavailable”,实际上就是EAGAIN。这个错误可以通过我提供的一个patch来补救(这个patch当中还包含其他的一些修复,所以请自行查看并修改该patch)。

由于以上的一些原因,server process模式作为一个对象的共享模式,能够提供最为灵活的共享方式,但是也有最多的问题。这个在使用过程当中就靠自己去衡量了。目前我们的系统对于数据可靠性方面要求不高,丢失数据是可以接受的,但是也只用这种模式来维护统计值,不敢用来维护更多的东西。

关于跨进程共享对象的问题就写到这里,后面内容待续……

test_sharedvalues

OpenInkpot 0.2正式版发布

2009年12月6日 没有评论

OpenInkpot的负责人dottedmag刚刚在OpenInkpot的官方用户列表当中宣布了OpenInkpot 0.2的发布。这个历时一年的版本终于发布了。从0.2版本开始做我就基本上在参与Wiki的中文化和界面的中文化,如果有任何关于中文翻译的问题,可以通过 @ftofficer, ftofficer@ftofficer.com联系到我。

0.2之后,马上就要开始0.3的开发。根据之前的计划,0.3将会在PDF的处理性能,更多的设备支持,更多的格式和应用软件方向发展。

下面是dottedmag的宣布邮件的翻译:

我们骄傲的宣布OpenInkpot 0.2的发布。OpenInkpot是为电子书阅读器和电子纸屏幕设备设计的自由和开源的固件。

在开发当中(相比于0.1)几乎所有的代码都被重写了,因此不可能提供一个完整的更新列表。值得注意的更新包括:

设备支持

  • 新支持汉王N510和汉王N516

功能

  • PDF 和 Djvu 阅读器
  • 简单的图像查看器
  • 简单的音乐播放器(仅为汉王N510和N516提供)

界面

  • 14种语言的新界面
  • Azbooka提供的新的界面观感
  • 屏幕旋转
  • 屏幕锁定
  • 低电量警告

其他

  • 添加了大量的新的益智游戏

文档

OpenInkpot 0.2 可以在这里下载

http://openinkpot.org/pub/releases/0.2/

米哈伊尔 古萨罗夫,代表OpenInkpot项目组。

标签: ,

OpenInkpot 0.2 rc5和rc6试用手记

2009年12月6日 没有评论

OpenInkpot 今天推出了rc6版本(下载)。RC6的主要还是以修复bug为主,增加了两个新功能,一个是增加了djvu格式的支持,另一个是支持在书架视图当中显示书籍的元数据信息,例如作者等。

连同之前推出的rc5版本,rc6已经基本上具有了可以发布的质量,尤其是rc5开始的对PDF阅读器LocolPDF的优化,使得PDF的阅读速度大大提升,虽然尚不足以和官方固件媲美,但是速度已经可以接受了。而rc5新添加的PDF“匹配文字宽度”模式,更是达到了官方固件切白边相同的效果。比起官方固件只有三级放大,OI可以支持在按文字宽度匹配的基础上微调文字大小,可以实现更加细致的手工切白边,典型的是一些具有页眉的PDF文件,例如下面这张图,在书籍的右上角因为有页眉,如果使用官方固件,则右侧会有大片空白,效果如下:

自动切白边的效果

自动切白边的效果

但是使用OI,则可以按阅读器右侧的放大按钮,使得文字充满页面(见下图):

手工切白边的效果

手工切白边的效果

而RC6的新功能:在书架模式下面显示文件的元信息则给我带来了点小麻烦。因为我的PDF文件当中的元信息大部分都是不对的,一部分是因为我没有认真的设置它们,另外有些网络上下载到的PDF当中的元信息也没有很好的设置。而且,对于具有中文的元信息,有时候会有乱码。这个新功能是最近才加入的,因此可能有很多问题,作为绕过方案,dottedmag建议SSH到设备上,然后删除 /usr/lib/extractor-mini/*-pdf.so。

这个做法并不能彻底解决问题,尤其是乱码。考虑找一个合适的PDF文件,给开发者提一个bug。

标签: ,

招商银行专业版的几个问题和解决方案

2009年11月23日 1 条评论

用招行专业版有一段时间了,其间遇到的问题无数,而且每个问题都让我这个计算机专业人员极其困扰,客服电话也打了无数,每个平均半个小时,大多数问题都是在客服的启发下自己一个个尝试出来的,希望直接一个客服电话搞定也不太可能。

好在大多数问题都是兼容性问题,因为招行专业版本质上就是一个IE的壳,因此IE的版本和配置对于招行专业版有很大的影响。而且和国内的其他银行一样,为了保证密码的安全性,招行专业版使用了ActiveX控件来处理密码输入,这个ActiveX甚至会直接操作键盘驱动,因此,和其他软件常有冲突。这些问题大部分可以通过修改IE配置的方法绕过。考虑到未来有人会遇到类似的问题,整理一下放在这里吧。

明明网络已经连接,但是登录的时候还是报“通讯错误”,或者“xxxx不是有效的日期”之类的诡异问题

这个通常出现在安装了IE8的机器上,因为专业版貌似用了很多山寨的方式来包装IE,导致IE升级到IE8之后有众多冲突,两个冲突的大头是IE8的内存保护(DEP)和https证书验证。

首先是内存保护(DEP),这是个很有用的功能,可以极大增强计算机的安全性,防止很多导致中毒的恶意网页,但是偏偏和专业版有冲突,所以,使用专业版的时候,临时禁用它吧。方法是在IE的Internet选项当中的高级下面,将“启用内存保护减少联机攻击”前面的勾去掉。

另一个就是https证书验证。IE8开始检查证书吊销列表,这样可以保护用户免受一些被泄露的https证书的伤害。同样专业版和它冲突,(并不是说专业版的证书泄露了,只是功能不兼容)。方法是在IE的Internet选项的高级下面,将“检查服务器证书吊销”前面的勾去掉。

在转账、汇款等需要输入密码的地方,遇到“通讯环境内存操作失败

这个很可能是和机器上其他的密码控件的冲突,例如QQ的登录框当中的控件,360保险箱等等。正常情况下关闭QQ,禁用保险箱再重新登录即可。

-2009年11月30日更新-
今天升级了360安全卫士之后发现又不能用了,发现是专业版和360安全卫士的主动防御模块冲突。暂时关闭360安全卫士(同时会禁用主动防御)就可以了。

其它问题,持续整理中。

标签: ,

从电子书分发网络书仓网说说电子书阅读

2009年11月19日 2 条评论

今天偶尔在twitter上看到了@zheng非墙版),一位从事电子出版工作的同仁。跟踪他的Bio发现了网站epubsys,以及其旗下的三个子站:面向阅读者的电子书分享和分发网络书仓网,面向企业的出版物分发网络企业铺,和其核心产品虚拟印务。看得出来这个公司对于电子阅读有他们自己的一套 看法,试用了一下书仓,感觉还不错。可以用多种格式下载电子书,可以自己在线制作电子书。假以时日,希望这里会变成我的主要阅读来源。

对于电子书阅读方式来说,通常可以归结为几种媒介:PC,手机和其他便携设备,电子书阅读器。本人有幸同时使用这三种媒介阅读电子书,下面就我的看法说说这几种不同的媒介的特点。

其中PC具有良好的带宽和运算能力,在线阅读和下载阅读都可以有很好的体验,弱点是无法随时随地阅读,同时这也是个优势:更加适合大块时间来阅读。但是PC的液晶屏对眼睛的损伤导致阅读体验并不非常好。

手机具有便携性和较好的网络访问能力,但是手机的屏幕较小,电池续航能力有限,不适合长时间阅读;手机的优势也是显而易见的,可以随时随地访问到实时内容。因此手机比较适合阅读新闻或小品文,不太适合逻辑缜密需要仔细思考的长文章的阅读。

电子书阅读器(特指基于e-ink的专用电子书阅读器),根据不同的厂商,可能有网络访问也可能没有,便携性尚可。其卖点是电池的续航能力和e-ink类似纸张的显示方式。这个更像是在手机和PC的中间层当中寻找市场,提供便携的大段时间的阅读,例如飞机和地铁。同时这一类阅读体验更加受Geek的欢迎。

因此,一个优秀的电子书阅读器分发网络必须同时考虑这三个途径,Amazon从基于eInk的Kindle开始,然后推出手机(iPhone)的阅读客户端和PC客户端,就是走这样一条道路。这一点书仓网做的不错。唯一不足的是,电子书阅读器尚且没有很方便的支持。实际上这个不能怨书仓,因为电子书阅读器现在尚且年轻,系统相对专用和封闭。不过随着其发展,OpenInkpot这种开源的固件和NOOK这种基于Android的阅读器应该会更受欢迎。

考虑到手机和电子书阅读器这种设备的时候,有另一个需要考虑的问题就是书籍同步。由于厂商的差异,有的设备是无法实时访问网络的,因此需要一个PC端的软件进行管理。这个可以参考Apple的iTune + iPod的模式。PC端软件专注管理,设备专注阅读。

可惜的是,国内的设备制造商们并不看好这个电子书分发网络的建立,翰林不必说,一个校办工厂可能觉得,能够做到OEM/ODM很多产品已经不错了;而国内另外一家汉王,则认为预装才是硬道理。而他们的完全基于目录的书籍管理方式,则明显看出来并无意关注书籍管理方面。

对于我们的需求和厂商的思路这对矛盾,可以选择两种:选择Kindle或NOOK这种基于某个厂商的设备,或者自己动手,丰衣足食。如果选择后者,依赖OpenInkpot改造设备,再依赖书仓进行书籍分发和发现,足够。

但是OpenInkpot现在缺少一个优秀的客户端。这就是我最近在做的东西:liboi – Computer side OpenInkpot management library.