您的位置:首页 > 其它

盗梦终端:如何进入第1000层梦境(另附函数大战实况)

2010-09-14 00:11 253 查看
“盗梦空间(Inception)”刚刚在国内上映那会(2010年9月1日)我就去看了,确实是一部好电影。后来还在网上看到说盗梦空间就像是一层层的“函数调用”,确实很形象(见此:Inception:一场层层调用的函数大战)。
今天看推时,突然看到一条,说是Shell有个变量:$SHLVL,是查看当前Shell的级别(Level)。我立马一试,果然如此,简直就是Inception的翻版!
我们在使用Shell(以Bash为例)的过程中,实际上就是一个Inception的过程:执行一个脚本的时候,并不是在当前的Shell环境下执行的,而是另起一个Shell,在里面执行,执行完毕后,销毁它,并回到当前的Shell。
一般情况下,我们的Shell都是第一层,如图:

如何进入下一层呢?只需要不停地执行自身(bash)即可,如图,执行了三次bash后,成功进入了第四层Shell:

与Inception一样的是,想要回到前一层,必须得执行“exit”完成任务,或者被“kill”。假如很不幸第一层被kill掉的话,后面的N层梦境都没有了(父进程退出,子进程也遭殃)。
问题来了:Shell到底支持几层梦境呢?在看了Bash的源码后,我发现它竟然支持1000层!在Bash源码的variables.c,约4680行左右中有这样的定义:
if (shell_level < 0) shell_level = 0;else if (shell_level > 1000){ internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level); shell_level = 1;}
也就是说,超过1000层后,又回到第1层,也就是现实世界了?
于是我就想进入1000层看看,如何方便的进入第1000层Shell呢?for loop一次次套一个bash命令肯定是行不通的,因为在进入下一层Shell后,上层的Shell的命令就不再对这层起作用了。
我想了很多方法都行不通,最后只好去请教神通广大、无所不能的华主席(@shellexy)。华主席就是牛逼,马上就给了一个解决方案,用Pygtk来Inception至N层!
原理是这样的:
使用GTK+的vte库来创建一个虚拟终端,通过vte.Terminal的paste_clipboard方法,不停地注入“bash \n”,于是该Terminal就能按照你想要的方式进入N层梦境了。源代码如下:
#!/usr/bin/pythonimport vte, gtkwindow = gtk.Window()window.set_default_size(480, 320)window.set_title('Inception')window.connect('destroy', lambda *w: gtk.main_quit())sw = gtk.ScrolledWindow()sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)term = vte.Terminal()term.set_emulation('xterm')sw.add(term)window.add(sw)window.show_all()term.fork_command()clipboard = gtk.Clipboard()for i in range(1000): clipboard.set_text('echo SHLVL \n bash \n') term.paste_clipboard()gtk.main()
代码很简单,基本上不需要讲解。关键的便是clipboard的剪贴版操作及terminal的粘贴动作。
不过,如果你想真正进入第1000层,可是有点难的。这要取决于你的电脑是否有够强劲的CPU,是否有足够的内存——当然还有你是不是有足够的耐心。
在我的电脑上,我跑了很久……基本上是这篇日志开始写的时候开始跑的,一直到日志写完,还只有进入第三百多层,接下来每一层的进入都会花很多的时间,可以说是越来越慢。同时,我的物理内存(2GB)已经消耗完毕,开始烧SWAP了。
来两张图吧,壮观的“盗梦终端”:每一层都在“do_wait”下一层的完成……

pstree命令的效果:bash-bash-bash……实在是显示不过来了。

写完这篇日志时,我已经Inception至四百多层了,SWAP大概还有1700MB,看似可行,不过同时我的机器反应速度也越来越慢了,我还是先把日志发表了吧~
操作系统的世界,还真是跟现实相当类似啊。当然操作系统世界要比当前人类世界领先多了,比如fork(),哈哈。
我在想,要不大家来一个Inception至一千层的比赛,看谁的机器比较给力,能在最短的时间进入呢?

注: 就有这么凑巧的事:上周还在看侯世达 (Hofstadter)先生的《集异璧》,这周就在电影院里看到了书中概念的演绎版——哈,说的当然是日前火爆酷炫的高分电影Inception啦。废话少说,赶快剧透。还没看过的同学们海涵了,虽说透穿了剧情也不会影响你观影的效果。
Inception抓人眼球的是它“梦中做 梦”和盗梦的情节设计。在层层深入的梦境里,人的意识逐步放松警惕,入侵者便可以趁机盗走储存在大脑中的信息。控制梦中的意识,“我做你的梦”,两个 人的思想在同一个大脑中争斗……这都是令人看得过瘾的狂野想象。然而身为一个业余程序员和《集异璧》忠实读者,看到人在梦里死了掉进迷失域(limbo) 再也出不来,我第一反应还是忍不住叫出来:“哇,堆栈溢出!”
堆栈是一个计算机术语,我看来看去,觉得Cobb这群人在剧中完成任务的方法就像出自程序员的手笔。你看每个梦,都是同样的一组人物,抱着同样的目标,只是换到了不同的场景里。这多像一个函数调用的过程啊。
也许你没听说过函数调用,但你也许炒过青菜。 通常我们会先热锅、放油,然后爆炒、加盐、出锅。那么从热锅到出锅的一整套动作就可以写一个名为“炒”的函数。如果我们为白菜调用这个函数,就完成了“炒 白菜”的任务;如果为空心菜调用这个函数,就完成了“炒空心菜”这个任务。你还可以自由发挥,为各种包菜、韭菜、胡萝卜调用同一个函数,就把它们都炒了。

Cobb先生当然不在乎炒的是什么菜,他的任 务是在Fisher的脑中播种下拆分公司的念头。他为Fisher先生设计的函数就是梦,让Fisher的潜意识瓦解的梦。在计算机程序中,一个函数内部 可以调用另一个函数,在第二层函数运行的过程中,第一层的函数就在等待,直到第二层函数返回了运算结果,第一层函数再利用这个返回的值来继续它自身的运 算。这么一比较,Cobb的精心设计实际上就是用一个梦去调用另一个梦,上一层梦境中熟睡的人们都在等待下一层梦境中的人完成任务。一旦成功,就用音乐或失去平衡的方式返还(在迷失域则是死亡),来结束上一层梦境。

就像程序员喜欢在函数中调用函数来使问题步步细化,这些嵌套在一起的梦也起到了步步逼近Fisher内心深处的作用。但是这样层层的调用也有个风险,万一信息链被破坏,函数不知道自己身处的是哪一层,事情就要乱套。这样就使得“堆栈”这个概念变得重要了。
在计算机语言里,“栈”是内存中的存储区,它保存着正在运行中的程序的临时信息,在程序完成后就被新的程序信息覆盖。“堆栈”就是向这些存储区写入信息,好让系统知道现在哪个函数在等待返回值,以及返回来的值要到哪里去读取。
但是计算机的内存容量是有限的。当函数调用的 层数过多,新调用的函数信息在写入内存的时候空间不够,就把一些老的信息覆盖了。麻烦的是,被覆盖的那层函数还在等待下层函数的返回值来完成暂停的任务。 这样虽然新的函数成功运行,老函数却没法正确找到返回值,整个程序就出错了。这种因为空间不够而产生的错误覆盖,就是开头提到的堆栈溢出。
这和情节有什么联系呢?当然有啊,Cobb的 老婆Mal不就是堆栈出错的受害者嘛。根据影片情节设计,Mal在迷失域中就因为待得太久而失去了对现实的记忆。她一直在最底层的函数里,却认为活在最顶层的现实,不需要返回到任何地方。而Cobb的“栈”还是完好的,他还记得 现实中的孩子,知道应该返回到顶层去。
这个时候,如果Cobb直接带着Mal卧轨, 不和她说那些有的没的,两人也许就安全地从底层返还了。但是Cobb犯了个错误,他对Mal的潜意识进行了修改,这就相当于故意在Mal的“栈”里放置了 错误的但是有意义的数据。这样当Mal回到最顶层的现实时,本来整个大程序应该宣告结束,但因为她的“栈”被改写了,这个程序就错误地认为自己并不在顶 层。于是Mal就失去了对梦境和现实的分辨力,觉得自己应该再死一次才回到现实。
“悲剧啊!”看见Mal坠下高楼,我不由叹息,一出内存出错的惨剧。
与其说这是一部关于梦的科学幻想,倒不如说是 利用人类的算法对意识进行的一次设计。据说影片的灵感有部分来自侯世达先生的《集异璧》。这是本涉及甚广的奇书,试图综合各学科的知识来探讨意识的机制。 侯先生虽然也不能完全回答自己提出的这个问题,但他猜想意识的关键之处在于“我”这个概念的产生。而这个概念来自自我和外界的区分,来自人类和外界不断的 信息交流。于是对“我”的认知从出生时起就一层层叠进脑内,这种交流积累终其一生循环往复。书中曾把这个过程类比于函数对自身进行循环调用,那么影片中的 故事设计与计算机原理相似的情况倒也不太出乎人意料。
咦,那么有没有可能,导演在试图把计算机科学的知识植入到我们的潜意识里面?银幕前面的你,被他的Inception施中了吗?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: