有义务鉴别小偷的公园【续】

2009年12月27日 1 条评论

继续上一篇,有人提出,我在这个例子当中关于公园和小偷的比喻不恰当。确实是不太恰当,因为信息产业相关的东西,想要实体化总是会很难找到完全相似的比喻的。所以我觉得有必要再写直白一点。

先引用一下前面的朋友的评论:

其实我觉得你的比方不恰当,关键在于是否可以标识出小偷:公园的例子不合理在小偷和普通人是混在一起无法标识的;而互联网服务商中的情况则不同,在完全可 以认定并确定是谁的情况下,是应该对违法者[至于那个使用服务的违法用户违反的法律合理与否暂且不讨论]采取删除等措施,因为你是在这个国度,在没有能力 不遵守游戏规则的前提下还是必须要“依法行事”的。

其实我的本意不是在识别小偷这个地方,互联网服务本上就导致识别身份不是问题。我主要关心的是给你一个人,确定其侵权指控是否成立的问题。偷东西这个比喻的问题是,它太好界定了,偷了就是偷了,没偷就是没偷。而侵权,尤其是侵犯了隐私权这个问题就不好界定了。一个网络服务提供者是否有能力认定一篇文章或者一个帖子侵犯了其他人的权利?比如说,我的个人资料在blog上面是有的,别人贴到了其他网站上,这个算不算侵犯了我的隐私权?你我都说不清楚,同样的网络服务提供者也说不清楚,因为《侵权法》没有规定。法律将这个没有明确判断标准的东西施加给不具有司法权力的网络服务提供者,其实是有问题的,服务提供者为了防止潜在的连带责任,会倾向于认定侵权成立,会造成侵权认定的扩大化,损害信息发布者的权利。

另一个问题就是,服务供应商需要确保所有在其平台上发表的信息都是经过审查的,因为有第三款。预先审查对于服务提供商是个巨大的成本,而且具有极大的不确定性。这也是我在公园这个比喻当中主要要说的问题:新法律的实施,将使得网络服务提供者的门槛大大升高,甚至挤死正在成长的网络服务。当然了,这个说不定就是法律制定者的目的所在。

最后一个问题就是《侵权法》没有规定服务提供商错误认定的情况下的措施,其实是默认了服务提供商错误认定的免责,同样很容易造成侵权认定的扩大化,因为服务提供者删文断网是没有风险的,这样对于信息发布者和网络使用者都是不利的。

这也是我旗帜鲜明的反对这条法律的原因。而且我并不赞成你我没有能力改变这个情况,因为这些“没有法律规定的”区域,通常是留给最高法院进行司法解释的。司法解释通常在司法过程当中积累经验,因此我考虑人大常委会其实对于错误认定的情况没有定论,因此将这个问题推迟到司法解释进行,先看看大家的反应如何。我们能做的就是在我们作为信息发布者和网络用户的权利受到服务提供商认定扩大化侵犯的时候,使用《侵权法》本身对该问题提出质疑,声音多了,司法解释自然也就出台了。这种时候就是会哭的孩子有奶吃。虽然我们的政府做事非常独断,但是对于影响经济发展的问题还是可以有讨论空间的,因此我们不必非常悲观,能做多少做多少。

标签: ,

有义务鉴别小偷的公园(关于侵权法互联网专条)

2009年12月27日 2 条评论

我家门口有一个公园,不收门票的,人们可以在这里聊天碰头谈恋爱,该公园提供椅子、草坪、游乐场等服务,有的免费,有的要收费,人们在这里玩耍聊天增进感情,公园在一些位置上安放广告来盈利,虽然偶尔传出有人被偷钱包了,但是有公安局和派出所,所以大家并不担心。一切都很和谐。

某一天,这个地区的一些官员在这个公园被人偷了,于是说,我们要保护大家不被偷,因此颁布了一条规定,要求公园必须设立一个办公室,如果有人冲进去该办公室,说我被一个人偷了,我口袋里有他留下的指纹,那么公园方面有义务立即从大批人群当中找到该小偷,并且立即将其赶出公园,否则如果这个人再被偷,或者再有人被偷,公园将承担连带责任。

而且,法律还规定,如果公园知道有人会被偷,还放小偷进来,也需要承担连带责任。

你觉得,这个规定是否合理?

按照常识,我觉得不合理。因为第一,偷东西的是小偷的行为,公园没什么责任,因为在其他地方也可能被偷,而且被偷的人只要去报警就行了,公园可能需要合作提供大门口的监控录像之类,但是出了事不应该去找公园。

第二,公园没有不应该判断一个人是不是小偷,而且他也没有这个能力,这些是司法机关应该做的事情,不是一个公园有能力做的。

第三,公园在没有能力判断冲进办公室的人说的是否是真话,因此可能把无辜者赶出公园。被说成是小偷的人可能说那个冲进办公室的人诬告,公园不知道谁说的是真的,也不应该由公园判断。

第四,公园听信一个人说的话,把一个无辜者赶出了公园,这个无辜者后来被证明是被诬陷的,那么公园是不是应该为他被赶出公园赔偿?很遗憾,法律没规定,因此公园说我们不赔偿,而且以后,不管什么人,只要进来说我被偷了,然后指着一个人说是他偷的,这个人就会被毫无代价的赶出公园。

因此,这条法律,完全违背了常识,试图让一个公园担当公安局应该做的事情。最后的结果,很可能是大家都不去这个公园,或者是大家都去了剧院,因为剧院不受该法律管辖。公园会越来越难经营,然后倒闭,然后公园被推平,开始建造天价商品房。

如果你看明白了我说的这个故事,那么看看现实生活当中的事情:

昨天(2009年12月26日)胡锦涛签署了第21号主席令,《中华人民共和国侵权责任法》将于2010年7月1日起施行。我们的胡核心在周末还在加班工作,不知道有没有加班工资。看看其中的第36条,又称互联网专条,提出了关于互联网服务处提供者在侵权案件当中的责任认定。

第三十六条 网络用户、网络服务提供者利用网络侵害他人民事权益的,应当承担侵权责任。

网络用户利用网络服务实施侵权行为的,被侵权人有权通知网络服务提供者采取删除、 屏蔽、断开链接等必要措施。网络服务提供者接到通知后未及时采取必要措施的,对损害的扩大部分与该网络用户承担连带责任。

网络服务提供者知道网络用户利用其网络服务侵害他人民事权益,未采取必要措施的, 与该网络用户承担连带责任。

可怜的网络服务提供者们。

标签: ,

liboi 0.0.2 – 为OpenInkpot提供客户端支持

2009年12月27日 没有评论

完成了liboi 0.0.2版本,发布在了google code上。

0.0.2版本增加了文件移动的操作,可以将文件拷贝到设备上,或者从设备上拷贝出来。

下载:http://code.google.com/p/liboi/downloads/list

接下来开始做到Windows的移植工作。

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

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项目组。

标签: ,