青春

</embed>

这个标题下大多都会有一个伤感的故事

因为当想到这个标题的时候

这个字眼就已经离去了

不知道为什么

一想到要离开帝都就莫名的兴奋和冲动

好吧,其实我知道

Published: 20 Jul 2012

历史的忧思

算是对《近距离看美国》系列的一个读书笔记,其实一开始不想写了,因为就看第一本的时候比较有感触,再往后看就产生了世界本来不就该是这个样子么的幻觉,就觉得也没什么意思了。直到最近被一些事拉回了现实,就又想翻出来写一下了。再者本来开博客的动机之一就是不会被人莫名其妙的和谐掉,于是如果不写一些敏感、不正常、别有用心的文章就总觉得自己亏了。不过想到我是在这么一个所谓有着光荣传统,所谓担负着历史使命的学校,于是我就作罢了。毕竟我不像韩寒、李承鹏那样有着名人光环,也没有一个方舟子在每当我写一篇东西就积极的向世人证明这不是我写的。写一些读这一系列书的感受,不作任何联想。

民主和自由

其实略微一细想就会发现民主和自由两个词尽管总是同时出现,但这两个词在字面上的意思却是冲突的,就好像专政和自由冲突是一样的。如果少数服从多数的话,那么少数人的自由就可能被侵害,而这少数人有可能永远无法通过自己的力量来保护自己。而基于人是会犯错误的假设,永远无法保证多数人的做法就是对的,多数人都狂热而导致少数人受到迫害的所谓 多数人暴政 还是很多见的。德国对犹太人的灭绝,美国白人对有色人种的歧视都是多数人对少数人的民主,包括几十年前文革那场轰轰烈烈的运动,这种假定多数人就一定是正确的观点在历史上也是站不住脚的。

不过当听到有人说中国人不适合民主的时候,我就方舟子了……你怎么证明,怎么证明,麦当劳能证明么?肯德基能证明么?太平洋那边的殖民地经过二百来年都演化成公认的成熟的民主制度,再近一点,从1863年的《解放奴隶宣言》来看,当年是奴隶的黑人都能当总统了,中国人是不是特殊了那么一点点,而且南边那个传统文化保留的比大陆要好很多的小岛上的民主实践貌似也在步入正轨。如果说民主的推进会带来流血牺牲的惨痛代价,结果也不一定就比专政好的话,代价太高的话,那么想一下那些在政治迫害、三年风调雨顺的自然灾害、计划生育中离开这个世界的生命话,这种规模和速度,再往历朝历代看看,再往世界各国扫一眼,我觉得民主的代价似乎是高了那么一点点。

枪在手

美国的各种枪击案让人觉得这是个很不靠谱的地方,找我原先的想法,怎么能让普通百姓有枪,这岂不要造反么?看了美国宪法的修正案,发现美国宪法还过分,不仅要求保证人民拥有武器的权力神圣不可侵犯,居然还要求每个州必须有自己的民兵。这里的民兵可不是什么预备役之类的东西,照解释宪法那帮人来说当年美国能独立就是因为有民兵,所以民兵是用来抵抗联邦政府的……然后我就在书里看到了总统为了帮助一个黑人孩子入学带着联邦军队和州长带着民兵对峙的故事,然后我觉得这在中国哪个省长敢这么做这就是反党,反人民,颠覆政权,分裂国家,打入十八层地狱永世不得翻身了。可是在美国完了就完了。

其实美国历史上也是有着国家分裂的,有着和我们国家解放战争差不多的南北战争,什么南方早期占优势,北方获得民心取得最后胜利之类的套路,但美国对南北战争的反思似乎要深刻一些。这个战争的发展过程大概是这个样子的:

北方:哎呀,我们要以多数优势通过废除奴隶制了,哈哈,南方你们终于要听话了。

南方:算了,那我们退出联邦好了,兄弟们跑路吧。

北方:你们分裂国家,你们破坏统一,你们千古罪人!

南方:我们加入联邦本来就是自愿的,凭什么加进来就不让退出了,共产党还能退党呢。

北方:你们分裂国家,你们破坏统一,你们千古罪人!

南方:当年你们《独立宣言》的时候不说过政府压迫的话可以另开门户么,你们独立的事都忘了么?

北方:你们分裂国家,你们破坏统一,你们千古罪人!

南方:你们能说点别的么?

北方:雄赳赳,气昂昂,跨过鸭绿江。(不说了,反正不占理,直接打丫的)

南方:喂!你们发动战争是违犯宪法的。

北方:呵呵

南方:喂!你们侵略呀,你们烧毁我们家园,屠杀我们的人民!

北方:呵呵

南方士兵:保卫长江,保卫黄河,保卫全中国!

北方士兵:貌似咱们发动战争没什么道理呀。

北方:这个战争呀……我想说的是……首先它是一场战争……所以呢……绕开各种因素来说……它不过是个……是吧……我们换一个角度来看……它还是有独到之处的……至于为什么这么多省略号呢……对吧……明白了吧

北方士兵:…………

北方:啊,对了,我们发动战争有一个无比神圣的目标,我们要解放黑奴!

南方:少来了,你是觉得联邦有人退出你脸上不好看。

北方:奴隶制好黑暗啊,我们怎么能容忍这个制度存在呢。

南方:奴隶制又不违法,你凭什么打我。

北方:啊,我们这就立宪,宣布奴隶制违宪。

南方:我都独立了,你管得着我么?

北方:你违宪,你违宪,兄弟们上啊,打他!

南方:我能说脏话么……

最后北方通过战争途中的偷换概念骗得民心,获得了胜利,其实本质上这就是一场统一全国的内战。让人感慨的是,尽管南方失败了但却没有遭到所谓的胜利者严酷制裁,大家更多的是对战争的反思。战争一旦运作起来很多事情就说不清了,留下的是人员的伤亡和家园的毁坏,如果胜利的一方大唱功绩的话反而让人质疑。

上面就是有枪有民兵可以随时起义造反的后果,但是如果人民没武器又会怎样呢?总有人说中国人有根深蒂固的奴性,但是如果一把枪举在你面前,你手上没有任何防身的东西该怎么办呢?宁死不屈,死磕到底?如果有枪的话,城管们就不敢欺负路边小贩了;拆迁部就不敢强拆民房了;警察也不敢随便闯门逮人了;武警也不敢随便扔闪光弹了……为什么不敢打黄岩岛,敢打游行的人,乱七八糟分析那么多不就因为菲律宾有武器,游行的人没有么。既然外面的人已经用武器把政府逼成这个样子了,我等草民还是老老实实的不要给政府添麻烦了吧。

人是靠不住的,政府也一样

由于美国建国那帮造反派们都认为人是会犯错误的,不存在十全十美的人,所以他们制定的宪法花费了大量的心思都是在限制政府的权力。因为一个不靠谱的人掌握了足以毁灭国家的权力,后果是很可怕的;同样让一个政府掌握了毁灭性的权力同样是可怕的。所以看美国的宪法讲的全是政府不能做什么,这个不能做,那个不能做,这个能做但要和国会商量,那个能做但是要最高法院同意,诸如此类的条款,很少看到政府能痛痛快快的做一件事。

由于制定法律,解释法律和执行法律是三套系统,所以在美国经常看这三个系统掐架,总统刚宣布要对华友好,国会给一票否决了,于是大陆媒体就可以高唱某些国家不顾大国形象反复无常,说话如儿戏。其实这么分散的权力系统发出一个共同的声音还是很困难的,哪像党政军,公检法上下步伐统一的系统。

Published: 04 Jul 2012

操作系统启动之谜

在我小的时候一直纳闷一台电脑是怎么从给它个电就能自动跑出一个五颜六色的界面的,相信很多人也有和我一样的疑问吧。长大之后总算多少了解一些了,试着把我的了解和疑问写一下。PS:可能今后会有一段不方便更新博客了,不过也只是可能,不过既然有可能了,这次就多写一点。

先考虑一个普通的程序运行,会有各种通用寄存器记录一些变量,一些状态寄存器记录程序状态,eip寄存器记录运行的指令地址;内存中会有代码段,数据断,堆和栈;然后就按照当前的eip地址从内存中取指令,指令再根据各自的寻址方式选择从寄存器还是从内存中读取数据进行运算,如果开启虚拟内存机制,数据页面可能在硬盘上,此时会有磁盘IO。计算机的启动实际上也是一个程序,执行一系列的指令,修改一系列的数据,那么计算机的启动和普通程序有什么不同呢?

史前时代

正如我们所知寄存器和内存这种存储器都是易失性存储器,一掉电他们就清白了,一开机是有作坏事的能力了,问题是谁能给出第一个eip?这第一条指令的eip又该是多少?好吧,就算eip有了,eip去内存取指令了,可内存此时应该也是空的呀。我们知道程序要在内存中才能运行,其他程序可以靠上一个在内存中的程序把自己加在到内存,那么第一个程序怎么把自己加载到内存呢?

从现有的计算机体系角度来看,软件是无法完成这件事情的,只能靠硬件来实现。由硬件把代码复制到内存的一个区域,再把eip置到那个区域就可以执行了,那么我们又该把什么代码硬件复制过去呢?如果你认识 BIOS 的话,这个时候他就登场了,它包括一系列的开机自检程序,对硬件进行初始化,设置中断向量,中断处理程序之类的工作。这部分代码是写在一个非易失的flash上的,硬件会自动把它加载到1M内存的顶部,为什么现在是1M内存就自己想去吧。不过我一直纳闷的是为什么要加载到顶部,加载到顶部的结果就是启动的第一条指令从地址到内容都是个十分tricky的设计。

其实写到这机器启动的第一条指令还没运行呢。因为尽管代码我们放到内存了,eip还没定下来。实际情况是BIOS代码的大小是不固定的,而硬件又把这部分代码加载到了内存的顶端,这样BIOS中地址最低一条代码的位置就不固定了,按照一般的编程思维,第一条指令就应该是地址最低的那条指令。而第一个eip的值又是由硬件写死的,怎么才能由一个固定的eip定位到一个不确定的地址呢?

先看一下实际中第一条eip是多少吧————0xFFFF0。对应于1M的地址空间,这个地址已经到了最后16字节,如果考虑到最长的指令有15字节和对齐因素的话,这个地方就只能放一条指令了,那应该放一条什么指令呢?事实上这个地方是一条跳转指令,跳转到BIOS 的低地址的第一条可执行代码。BIOS代码过把自己最高16字节的代码设为一条跳向低地址的跳转指令,这样就可以灵活的控制开机第二条指令的地址,来解决BIOS代码变化的问题。通过一个跳转指令,硬件和软件完成了交接,进入了一个我们相对熟悉的程序运行过程,BIOS的代码开始欢乐的跑起来了。不过我一直在想如果BIOS代码加载到内存从0开始的位置,第一条指令定位就没那么麻烦了吧。

远古时代

走到了这里所有的代码都是在BIOS的flash中代码,硬盘还没干活呢,也就是说操作系统还在睡觉呢。我们要把操作系统的代码弄到内存里来执行,然后就又碰到一个问题,装过操作系统的人都知道,操作系统可以装在不同的盘上,位置也是不固定的,也可能有多个系统,又该到哪去找操作系统呢?还是看一下BIOS在跑趴下之前干了什么吧,BIOS代码在内存中设置了中断向量表和中断处理程序,如下图,倒下前它发了个0x19号中断,这个中断的处理程序会把磁盘的第一个扇区加载到内存。

事情到这里慢慢有了头绪,尽管操作系统可能有很多位置也不固定,但是他们如果在第一扇区放个引导指向他们就可以了。实际上在第一扇区会存两个东西,一个 MBR(Master Boot Record)和一个加载程序。MBR中包括一段检查磁盘启动信息的程序和传说中的分区表。在分区表中就会记录每一个磁盘分区是否有可启动的操作系统,分区的大小,以及操作系统的位置。而那一小段加载程序就通过分区表来加载操作系统,grub就是这一小段程序的一个代表,它可以通过和用户的交互界面让用户选择进入的操作系统。这时候它会加载操作系统的第一部分代码,这第一部分的代码在最后又会加载第二部分代码,然后依次类推,一个链式反应就进入正常运行了,也进入了我们越来越熟悉的时代。

中世纪

操作系统现在其实基本就可以用了,很久很久以前最为简陋的操作系统,没有复杂的寻址模式,没有保护模式,没有操作系统自己的中断处理,差不多也就这样了。为了能兼容这种很就很久以前的设计,计算机启动还是保留着之前的步骤,但是时代总是在进步,所以启动过程也开始进一步演化。

首先要从实模式到保护模式的转化,在之时候要考虑一下原来什么东西是和保护模式不兼容的呢?其实主要还是地址相关的一些东西,可能在32位地址模式下就和原来不一样了。之前主要是有一个中断向量表是和地址相关的,需要把它进化成32位的,此时操作系统也想接管中断处理程序创建自己的中断向量表了,所以BIOS老前辈就要享受兔死狗烹的待遇了。但是在这时候如果有个中断请求正好过来,而中断向量表又在修改中,改了一个错误的地址那么机子刚起来就被打回到史前文明了,BIOS这个老油条还是留了一手的。所以在修改前操作系统会有一个关中断的操作。这样操作系统就可以毫无后顾之忧的修改BIOS的遗产了。

搞定中断向量后,操作系统只需要把相关的寄存器再初始化一次弄成32位模式的,初始化保护模式下GDT和IDT就可以开始保护模式时代了。然后地址线20位到31位在这一刻被激活了,我们终于可以利用4G的寻址空间了。

现代

其实没什么好多说的了,操作系统可以撒欢跑了。我也要准备考虑跑路了。

参考资料

  • MIT 6.828
  • 深入理解Linux内核
  • Linux内核设计的艺术
  • Published: 29 Jun 2012

    手稿集

    前阵子比较火的手稿集估计就是韩寒的《光明与磊落》了。当看到我最喜欢的调侃加戏谑的语句喷薄而出时,后悔晚了十多年才翻开这本书。喜欢这种每句话都透着灵气和想法的文章,不管正确与否,成熟还是幼稚,我相信能用心写出这样一部小说对作者来说也是一件快乐的事情。能够用心写出这样一部作品就足够了。

    记得韩少刚成名的时候我还是相当不屑的,只是故作中肯的说看他还能折腾多久,什么时候江郎才尽,甚至从来都没翻过他写的任何东西,只是幼稚的为了显示自己很正统。上大学的时候偶尔看到了他的博客,才觉得写的有那么点意思,语言的角度很奇特,看着给人很爽的感觉,他的博客也成了我Google reader唯一的非技术博。那时候还是当消遣文章看的,直到一篇叫《青春》的博文发表,我才开始改变对韩寒的看法,那份戏谑下沉痛的思考让我对这个人多了几分敬意。到后来《独唱团》的发布,我仔细看了每一篇文章,说实话我觉得《1988:我想和这个世界谈谈》之外倒是有很多精彩的地方。当然这部小说最后我还是看了,作为我看过的第一部韩寒的小说,表示相当无感。然后韩寒和方舟子今年年初的大战才让这部手稿集面世,我虽然很反感方舟子的作为不过对这个手稿集也没多大兴趣,我买回来的原因其实是因为听说字写的不错,嗯,字确实不错。

    当我翻到后面韩寒说创作《三重门》的经历时我才突然想起一件事来————爷在那个年龄的时候也写过小说啊好不好,我也有一本厚厚的手稿集啊有木有,三重门20万字,我当年完工的时候也有20万字啊有木有,我也是16岁就开始写小说的人呀,写的也是校园生活呀,也是上着课突然来情绪就写两笔啊有木有!想到这突然有种时空穿越感,为什么我小时候那么讨厌韩寒却还做着如此相似的事情我自己都没发现,现在看着人家写自己小时候的事却像找到了知己一样控制不住情绪。翻开了我的手稿集对照了一下,方舟子你个大骗子,说什么韩寒手稿集过于干净,我的比韩寒的要干净多了。

    翻开正文开始读就更受不了了,开头学钱钟书《围城》那样上来前压住气氛,再上几个稀奇古怪的比喻镇住气场,这种幼稚的花招我也用过,用的时候还洋洋得意觉得自己多么了不起。然后就是满篇稀奇古怪的比喻和反讽调侃,这种戏谑的语句是我当时写小说时候最喜欢用的东西,自己写起来也感觉最爽的地方。看样子少年的心都是一样的,谁在那个叛逆的时候都会有各种离经叛道的想法,不同的只是韩寒写出来了他就被大家认为是非主流,其实应该很多人在那个年龄段都和韩少有着相同的心境吧。我越来越脑不明白当年为什么这么讨厌韩寒了……

    当时也是我最爱玩文字技巧的时候,为了显示自己写的东西多么奇特,各种掉书袋引典故,以显示自己多么的能耐,我发现写小说很大一部分原因就是为了炫耀。记得我为了一句在电视上无意听来的句子可以精心设计出一个完整的故事情节,为了就是让这句话出来的时候很有分量。记得那时候班上有两位才子我还很不知天高地厚的要去和他们靠齐,在写小说的本子另半边抄了一堆红楼梦的诗词,汪国真的诗句什么的,装出一副文艺小青年的样子,现在想想我精神和气质上也就够做个伪才子了。当时为了显示自己的小说写的是多么的与众不同几乎每个章节都是换了一种叙述方式来写,而且还力图每一章节的语言特点看起来都不一样,这样好像是很多人合力写成的一样,以证明我的文字驾驭能力是多么的强悍,我的文风是多么的多变多么的挥洒自如。写到这我突然发现我要是被方舟子盯上会说都说不清……那段时间养成的习惯就是不管看书还是看电影全是看架构,看什么地方叙事方法精彩就在小说里来这么一下,记得我是看哪个鬼故事觉得构造的很好还在小说里用了。然后些小说还要各种埋包袱添伏笔,以给人读起来觉得作者控场能力很强居然能自如的把很久之前的东西连接起来。其实这种东西最好做了,就是想一个故事写一半不写了去写另一个故事,过一阵再些回来就行了。但是想到读的人被这些伏笔震撼到的时候自己还是很开心的。埋包袱埋多的后果就是现在养成看小说看电影的时候一直是猜剧情,因为我总是觉得他在哪个地方是在埋伏笔……很多电影和小说都被我看成侦探片了。

    小说从高一下写到大学开学,我是写上大学了,韩少是写退学了。当然这年头上大学不稀奇,退学或许才是韩寒受关注的地方,人们总是习惯于对做法和大多数不同的人抱有很难接受的态度。但韩寒还是在这种关注下成为了一个被越来越多人接受的公众人物,继续码着他的小说和文章。想到他只能码中文夹杂带点英文,我却还能码C/C++,Java,Python之类的我倒是也可以获得一些满足。

    现在再翻开我的手稿,看到那些当初让我兴奋的各种文字技巧,精心构造的句子,买起来的包袱都是显的这么的幼稚,尤其是换着风格写文章这种做法,害的我现在根本写不出一篇风格前后一致的长文。各种所谓的技巧其实不过是想急于证明自己多么不一样的幼稚的炫耀罢了,真正能触动我的还是里面简单但却真实的故事。慢慢的发现我之后的文章里秀trick的东西越来越少了,可能是写完那一本实在是把我的脑细胞耗尽了,不过也好,我越来越发现其实一个好的故事才能真正打动人。

    手稿我是不打算出版了,之前应了很多人写完可以来看,如果还有兴趣的话可以找我来要,不过之前没应过的就算了。一则这个东西已经过了最佳观赏年龄段了,为了避免我自以为开着一辆法拉利出去拉风,听到路边的人喊看看那个人买个奥拓还是二手的;我怒着下车让他仔细看他仔细看了一圈说原来奥拓也有人山寨呀;我的心灵暂时受不了这种打击。二则炒冷饭总让人有过气之感,虽说我也没成过气,三则年代久远,保管不利手稿已经有支离破碎的危险了。四则手稿的字写的实在是有些惨不忍睹。

    不过还是奖励一下能看到这的人,找一篇我当年装文艺装清新装的比较厉害的章节,也是小说的序,无删减版,话说我好想删呀。











    Published: 26 Jun 2012

    Learn the hard way

    前几天被人刷空间日志了,得出的结论居然是很励志……励志……要知道每个励志故事前半个甚至前大半个故事都是以凄惨悲凉作为主旋律的,如果一帆风顺的话就不叫励志了,那叫开挂。我不知道我是不是真吐了那么多槽才留下这么个“励志”的结论,反正下面的东西肯定不是一个励志故事。题目的出处参考Hard is easy,欢迎方舟子来打假,顺便说一句这个系列的编程教程我不是很喜欢,只是喜欢这个名字而已。

    这篇文章的大致意思就是说开挂状态下可能会很有快感,但是真正的收获可能不多,如果你一直觉得是在悲惨凄凉的 hard way 的话,反而可能会扎扎实实的得到一些东西。不过我想写的是在 hard way 上得贵人相助的事情。

    应该是在去年的明天的时候重回百度的,因为我印象里和百度有关的日子大多和20有关。然后很快就进入了混吃等死的状态,当时想的满脑子都是我该怎么找个机会离开这个地方,整个精神和状态都进入了低谷。(我好像说过不写凄惨悲凉的励志故事的)好在恰在这时组里的mentor回来了。现在想想上天还是蛮眷恋我的,能在最低谷的时候安排这么个好人来帮助我,让我不至于破罐子破摔那么下去。

    记得第一次上线由于我的失误留了个蛮严重的bug上线,结果却是mentor出来帮我挡住了rd,fe,pm的一顿狂轰乱炸然后才回来找我。如果她再对我狂轰乱炸一顿估计我就扔个离职书回家休假去了,因为当时对那个项目组也没有什么眷恋的地方,也不是很想再实习下去,当然我也确实该被狂轰乱炸一顿,偏偏她批评我的时候还笑盈盈的,整的我无奈了,只好回去乖乖的工作了。然后这一幕两个月内一次次的上演,每次上线我肯定都会有漏测的地方,然后她在外面帮我把火力吸引走了再回来笑盈盈的教育我,我再乖乖的去处理之后的事情。我也从一个混吃等死的实习生变成了一个每个项目都兢兢业业甚至可以为了一个项目熬一通宵的人,而这个过程中甚至都没人批评鞭策我,只是觉得让一个人在外面替我扛火力实在是太过意不去了,更受不了的是在外面替我扛完火力回来对我还那么好……只好强打着精神拼命工作,不过那一阵的状态实在太差了,总是会有疏忽的地方,不知道她是有怎样的宽容之心能够接受我的每一次失误,但我之后的项目确实都尽力了呀。

    突然想到袁腾飞讲课时问的一个问题:交往的时候你是要显示自己可爱的一面还是可怕的一面呢?朝鲜有核武器让你移民你去么?我就被mentor这样的糖衣炮弹活生生的自己把自己逼成了一个好员工。

    mentor技术上的神迹就不说了,给我最大触动的到不是她的技术而是对这个项目的热爱,这一点完全改变了我对工作的看法。我第一次意识到工作可以是因为出于这个工作的热爱,尽管她不是整个项目的boss但却对整个项目都很关注,为每个地方献计献策。有时甚至找到编辑录入的错误这种和我们那一圈技术口人毫不相关的问题,带的我们那一圈技术人员都开始给编辑挑文字问题,大家吃完晚饭就开始刷网页找编辑吐槽,弄的那帮小编辑们都怕了,自己开始制订提高质量计划了。她还发了一篇我们内部人写的最好的一篇游记帖,比一些请来的枪手写的都好,当时被推到首页放了好久,弄得我们大boss每次看到我们内部人发的低质游记帖都要那出她写的那篇给我们看,害的我们都不好意思发低质游记充数了。之前我还不能理解为什么她有这么大热情干这些事情,直到一次吃饭她和我说她当初来百度的时候技术根本就不适合百度旅游这组,之所以来到这组只是因为她自己喜欢旅游,技术什么的也是来了之后现学的。她之前的工作待遇其实也比百度好,来这里是因为喜欢这里年轻的氛围。

    然后我尝试着把对她的爱慕之情扩散到百度旅游这个项目中,发现当对这个项目有感情之后,工作似乎容易了很多,有些事情不用人催自己就着急要把它给办了,看到整个网站哪里有不好就跑到相关负责人那吐槽,有时候还自发的到网站上去和用户交流感情,整的自己和整个项目负责人一样。当时身边一圈的技术员差不多都被mentor影响成这个样子了,其实这样为了自己喜欢的东西工作,工作明显积极多了,也没觉得有很辛苦,有时看到有一点变化还觉得很快乐。现在想想蛮怀念当时的工作气氛,虽然有时很勤苦,但大家都因为共同热爱的东西而奋斗,不知道以后还会不会有这样的机会。不过mentor那“既选之,则爱之”的格言深深的留在了我的心中。

    记得她每次笑盈盈的批评我之后,都会改个hi状态,当然不知道是不是有什么直接联系,不过每次看到都有很大触动。然后我离开这将近一年的时间内的qq状态基本都是她当时的几个状态来回换,因为我总觉得对我鞭策作用很大,博客首页的tagline是她当时状态里我最喜欢的。本来还想再偷几个状态来换到我这来的,却发现这一年她状态都没换什么有实际意义的。虽说当时我已经是个要走的实习生了,她对我还是很照顾,教了我很多工作以外的事情,并且一个项目后就看出了我的缺点,这个缺点被实验室老师一年后才发现。每次我这个毛病犯的时候她还是照例那么笑盈盈的,一副装作要训斥我的样子教育我几句,告诉我以后该怎么办。照理说对于一个今后不在这正式工作的实习生,大部分mentor都是不会花心思去培养的,而她总是抓个机会就用那种让人无法拒绝的方式教导我一下。

    人生低谷之时得遇如此的贵人,确是一件幸事。至少今后回忆那段时光的时候还有一段如此让我值得庆幸的经历。最后一天离职吃饭的时候她说我很像她弟弟,好吧,就因为这句话她弟弟平白无故的被我嫉妒羡慕恨了好久。

    好吧,这应该是一篇感谢文不是一篇励志文,毕竟好运气是不能算励志的。最后附福利照一张,反正她应该看不到。

    </embed>

    Published: 18 Jun 2012

    栈溢出和堆溢出

    之所以想写这个东西是因为在我年幼无知的时候以为堆和栈是一个东西,然后迷迷糊糊的过了这么多年,直到那阵子面试前翻面经才把世界观给颠覆过来,之后又看了一些相关的东西,才发现这里面有这么多的奥秘,在这期间还发现本善良人手册写得很不错。

    堆和栈是怎样两个东西?

    栈在英语里是stack,堆在英语里是heap,两个完全不一样的东西。

    我们熟悉的栈

    栈是什么应该都很熟悉了,就是一个FILO的数据结构,不过他是用来干啥的呢?当然,他可以用来以各种奇怪的方式来遍历一棵树,不过他在操作系统里主要还是为各种函数调用,中断异常处理之类的东西保存跳转前程序运行的局部信息,使得这些跳转在完成后,程序可以恢复到原先的执行位置。具体情况就在下个图说明了,能把这个图讲清楚我就功德圆满了。

    这个图从哪说起呢?先从左边的两个指针说起吧。ebp是桢指针,其实我觉的叫桢底指针更容易理解一点,因为它指向的其实就是当前函数运行空间的桢底;esp是栈指针,指向了栈顶,ebp和esp的空间范围就是当前函数内存占据的空间又叫一个桢。然后就说说这个桢里有什么家当,首先是一个保存的ebp,它保存的是什么东西呢?它存着调用这个函数的函数的桢指针,比如说函数a调用函数b,那么在b的桢里面首先会存着a的ebp,这样当b返回时,推栈的时候就可以把a的ebp恢复回去。esp这个栈顶指针可以用来标志变量应该在那个位置进栈还是出栈,那ebp这个栈底指针又有什么用呢?如果你写一个C语言函数用GCC翻译成汇编代码就会发现所有局部变量的地址都是由ebp减一个偏移量计算出来的,ebp相当于提供一个基地址。为什么不用esp做基地址动动脑字想想就好了,为什么要减看看图最右边那个箭头就明白了。再往下是寄存器保存区域,按照IA32的惯例,ebx,esi和edi三个寄存器如果当前函数需要覆盖的话,要把他们保存,这个区域就是来保存寄存器的。再往下就是存当前函数的局部变量,临时变量之类的东西。再往下那个参数构造区域我就不知道是干啥的了,求大牛指点。

    ebp往上是调用者桢,首先是个返回地址,这样函数调用再返回时就知道pc应该填多少了,然后是n个参数,稍微注意一下这些参数是按从右到左入栈的。如果函数在运行的时候要用这些参数改怎么办呢,因为ebp已经不指向保存参数那个函数的桢了,没有办法用ebp减去一个偏移量来找到位置了。其实从图上很容易看出来,用ebp加一个偏移量就可以索引了。

    再往上就是其他的桢了,而这些所有的桢构成了进程的栈空间。每当调用一个函数时保存当前ebp,这时候esp会自动增长,再将ebp指向esp指向的位置,一个新的桢就建立了,再根据函数的变量情况,esp再继续生长。函数返回时从当前ebp指向的内存位置恢复,pc恢复成返回值,esp动态减少。栈就是这么生长和收缩的。

    堆又是什么东西

    先插个故事,当年去百度面试,大师觉得我实在是什么都不懂,就随口问了我一句堆和栈有什么区别,我说堆要用malloc分配,然后就混过去了……这其实还是在之前忘了去哪家公司笔试的时候有道问怎么在堆上建立一个数组我不会做,回去查出来的。这也是我一直想写这篇博客的原因,不过堆这块最后还是有很多不懂的。

    先说一下为什么要有堆,之前的栈的结构貌似很完美了,可以动态伸缩,层层调用,为什么还要有堆呢?想一下全局变量该怎么引用呢?这时候ebp也是变化的了,怎么才能找到那个绝对的位置呢?在每个桢里面都复制一份全局变量?或者通过栈底地址来计算?(其实我觉得这个方案单进程貌似还可以,如果多线程的话每个线程都会有一个栈就又不行了)另一方面,桢空间的大小分配是在函数调用发生的时候就确定的,有多少变量占多少空间就分配多大。不过就像刚才那个故事,世界上存在一个叫malloc的函数,而它分配的空间是不固定的,也就无法在栈里为它分配空间。如果非要强行分配的话,那么怎么通过ebp来确定每个变量的位置呢?另外操作系统为每个栈分配的最大空间是有限的,无法随意增长。

    所以为了克服这个问题就有了堆这个东西。在数据结构的概念里里堆是一个特殊的树状结构,不过在程序调用这个范围里堆是个简单的双向链表,将空闲的内存空间串起来,每当需要分配的时候就从链表中取下一块进行分配,在桢区只要保存一个指向这个位置的指针就可以了。另外在分配的时候还会在分配空间的第一块里存下分配内存的大小,这也是为什么当我们使用delete或者free这类函数不许要指定空间大小的原因。

    堆的工作原理真的好难找,书上讲得也语焉不详,上网搜给我蹦出来好几个核反应堆工作原理。大致说一下,进程中有一个空闲内存链表,每当mallco的时候就顺着这个表找到一第一块大于等于分配空间要求的截断下来,把剩下的空间继续链起来。当free的时候就直接再把这块空间给挂到链表尾部,这样时间长的话碎片就会很严重,可能找不到大小合适的空闲块,这时候malloc会开始进行整理合并一些相邻块。

    栈溢出及攻击

    好了下面开始启动攻击模式,看看怎么把程序整崩溃。

    记得栈里面存着什么不?有定位变量的ebp,它要坏了变量就找不到了,有返回地址,它要坏了函数返回就错了。问题是怎么让他坏呢?这就要用到溢出了,这种攻击相对简单,举个栗子就懂了。

    这个图是一个简单的函数桢,局部变量是个char型的数组buf[4]。然后在C语言里给char数组用gets函数赋值,因为gets是不检查赋值长度的,我们就赋100个字符给buf。根据之前讲过的东西,buf通过ebp定位buf的首地址为ebp-4。然后第一个到第四个字符顺利复制到buf+0,buf+1,buf+2,buf+3这四个位置。从第五个开始,事情开始起变化,5~8四个字符会复制到buf+4,buf+5,buf+6,buf+7,把保存的ebp给破坏,这样当函数返回后ebp就无法恢复到调用者的桢底,对变量和参数的定位都回发生错误。再往后四个字符把返回地址也覆盖了这样函数就不能返回到正常的程序流了,再往后,函数的参数也被破坏了,再往后上一个桢的局部变量也被破坏了。

    通过大量的非法输入来破坏之前的程序数据,这就是溢出的基本思路。然后很多心地善良的人就利用这个方法对程序进行攻击。由于返回值是可以更改的,这些心地善良的人就可以插入很长的一段非法输入,在里面包含一段自己写的善良的代码,这段代码也会覆盖的栈上,如果能把返回地址改成这段善良代码的首地址,善良的人们就可以成功的做他们相要做的事情了。当然说着简单具体怎么算出合适的地址和如写出一段有用的汇编代码还是颇费心思的,不过通往自由之门大致就是这个样子的。

    当然也有一股黑暗的势力相要阻挡这些人通往自由的道路设置了种种障碍,现在流行的方法主要有三种。第一种就是在每个桢首部随机插入一定的空间,这些空间唯一的作用就是让你不知道该怎么计算你的善良代码的位置和返回地址的位置。第二种是在函数返回的时候检查桢结构是否被破坏,具体实现方法是在桢上存一个变量,在函数返回的时候检查这个值是否被更改,这个方法还有个邪恶的名字叫金丝雀法。第三种方法是限制栈的权限,栈只有读和写的能力,没有执行的能力,这样恶意代码就被摁在那里不能动了。

    然后我研究了一下参考资料里的小册子,发现善良的人们已经找到通往自由的新道路了,任何黑暗势力终究是要败下阵来的。

    堆溢出

    这块那本善良人手册写得实在是太晦涩了,我实在是没看懂,求信安大牛拯救。

    大致思路是这样的,malloc分配出来的空间也是存着一个元数据的东西,分配块的大小,另一说是前一个空闲块地址,看得我迷迷糊糊的,姑且按大小来理解。当采用和栈溢出相同的入侵方法输入大量数据的时候,这块元数据的信息也会被破坏。如果把元数据改成负数的话,那么free的时候就会异常,如果改成个别的数,在malloc的时候可能会分配到已分配的空间造成重叠,balabala一堆破事。

    然后那本善良人手册上还列举了各种攻击方法,什么伪造空闲块,转移到桢栈空间之类的匪夷所思的方法,总之通过披荆斩棘,善良的人类又一次发现了光明。

    参考资料

    Published: 12 Jun 2012

    linux管道机制简介

    管道是linux提供的一种常见的进程通信工具,也是很多shell命令能够灵活组合产生强大用途的一个重要工具。本文就八卦一下它是怎么实现的。

    唉,看完这片,我打算还是从进程管理,内存管理和文件管理这三大块开始看了,一开始以为这些边边角角的东西会容易懂一些,结果老是用到这三大块的东西,总要回去查。

    管道是什么?

    管道,顾名思义就是个管子,里面可以流过去很多东西。举个栗子 ls | morels输出列出来的文件目录就通过‘|’这个管道流向了more这个文本浏览器。相同的功能我们也可以通过ls > tmp ; tmp > more来完成。实际上管道的功能和第二个方法也很像。管道也是一个文件ls的输出送到这个文件,more再从这个文件将东西拿走。所不同的是管道不同于普通的文件,是一套特殊的文件pipefs,在磁盘中没有映像,只在内存中存在,而且只存在于存在亲缘关系的进程之间。然后省略若干和文件系统,linux进程相关的知识…………好吧我还是说两句吧。

    为什么是特殊的文件?

    我们知道有句传说是linux系统中一切皆文件,事实上这句话很忽悠人,虽然都是文件一个文本文件能和一个CPU设备一样么。实际上常用的特殊文件类型就有十多种,之所以要把他们都组织成文件是为了应用级别的程序员编程方便,不管操纵什么东西,文件、设备、socket等等都可以open之后read,write再close,可事实上调用的底层的系统程序是不一样的。这个想想也知道,写一个文本用的实际操作和往一个socket写东西怎么可能一样。pipe特殊就在于它是进程通信的一种方法,这种发法要保证一定的速度,所以就不好扔到硬盘上去读写了,干脆就直接在内存上读写了,所以它成为一个文件只是为了接口的方便。

    至于说它只在有亲缘关系的进程间共享,是因为管道属于进程打开的文件,只有创建管道的进程fork出来的子进程可以共享这个管道的文件描述符,其他无关系的进程是看不到这个管道的,所以说是一种非常狭隘小资的通信方式。

    管道的创建

    管道有两个口,一个入水口一个出水口。pipe系统调用会返回两个文件描述符,一个文件描述符用来写一个用来读。如上图所示,两个file结构指向同一个inode,对应管道在内存种所获得的一片区域。这里稍微要注意的一点是,尽管我们平时的应用都是一个管道对应一个写进程一个读进程,但是管道本身是支持多个进程进行读写的,他们只要对相同的描述符进行操作,加之系统的互斥进程就可以实现多进程的通信。这里也可以看出管道是半双工的,没有一个文件描述符可以用来进行读and写,如果想在两进程间进行全双工操作就开两条管道吧。

    管道读写

    前面说过了,不同的文件类型的write和read操作是不一样的,那么是怎么通过一个统一的write和read来找到对应的操作呢?看一下write函数的声明size_t write(int fd, const void *buf, size_t nbytes),从进程这边传过去的唯一一个可能区分文件类型的就是这个文件描述符fd了,也就是通过这个fd文件系统会找到它到底是哪个文件,再去采取相应的函数调用。当然如果是write操作的话还要涉及到一些对内存加锁的操作。

    另一种管道FIFO

    如果说管道有什么缺点的话,就是它只能在自家亲戚中使用,不利于社会共同富裕,没有关系的进程就无法通过管道进行勾搭了。于是内核打算采用一种实名制的方式来登记一下管道,这就是FIFO。

    FIFO和pipe用的是同样的数据结构,同样的读写方式,不同的是内核为他们在磁盘注册了一个节点,这样所有进程都能看到这个硬盘上的节点,只要有权限就可以操作了,当然内容还是在内存中。并且这个实体可以用读写模式来打开,也就可以实现全双工了。

    其他的话

    上面都是一些机制的介绍。其实想写一下读源码的感受的,只是源码的感受过于琐碎,很难理出一个头绪来,而且源码的大框架是上面的机制,但看得时候注意到的更多是细节的实现方式,很多东西是和机制无关的。本以为这段的代码变更应该不会很大,但是看了一下commit记录发现变化还是很多的,很多新加的功能是除了注释找不到相关介绍的,只能自己从代码里推敲。还有一些改进方式是为了弥补以前的缺陷的,看这部分可以提升一些对系统整体的认识。所以鼓励大家在看过原理之后还是要看一下代码,代码中会有很多意外的收获,而这些收获又是很难通过别人讲述获得的。

    Published: 29 May 2012

    皇城根儿下的偷拍

    开学时计划去钟鼓楼看看,结果一个学期过去了,要么有事要么没心情。趁着今天闲赶紧过去慰问一下在皇城根下过着水深火热生活的帝都人民。

    下了地铁往胡同里拐,发现一条地铁正在往这片皇城里面开通,不知道会给这些古建筑带来什么。

    扫到了一个批萨店,有意思的是这个批萨店是个小桥流水式的中式建筑,让我想起了在798看到的那个咖啡厅。

    一开始是想找个古朴的门拍一下的,可惜这里的门要么上面贴着一些告示,要么周围挂着电表拉着电线,好不容易看到一个合适的上面贴的对联还都是什么和谐社会,不过最后还是找到了个比较朴实的大门。

    溜达到了钟鼓楼广场,看到了有穿着大褂的人在招呼着游人上车,不知道当年骆驼祥子是不是也是这个样子的。

    没有客人的车夫们就聚到一起聊起天来。

    聊不动了就用各种姿势躺下。

    钟楼和鼓楼之间有个小广场,附近的居民都聚过来晒太阳。一撮人凑在一起打麻将,脚下还躺着一只小狗。

    肯定也会有下棋的。

    一个老者在看着孩子们玩我当年玩的游戏,小时候我也蹲在下面玩过,不知道会不会有一天坐着看别的小孩在玩。在这个广场上驻足的都是老者和小孩,像我这种年纪的都是匆匆的过客。

    钟楼从外面看还是不错的,不过门票贵了点,而且里边除了个钟,就没什么了。

    当然这个楼梯还是给人留下了很深的印象。

    传说中的钟,多少年前敲一下这个钟,皇城附近的居民就都知道时间了,现在把它敲碎了我在学校也听不到了。讲解的小哥还是很风趣介绍旁边一张老地图时说“那时候国家大妓院还没建呢”。

    看见这个牌子想了一阵才反应过来想听个响还能这么弄,为什么不扔点石头什么的呢?

    发现了个探头,调戏一下,不知道有没有把我拍下来,说不定晚上我就被人带走了。

    在钟楼下看一下鼓楼。

    在鼓楼下回眸一下钟楼,我在想他们俩的关系是不是就和北科和地大的关系一样。

    鼓楼相对还是气派一些。

    换个角度再来一张。

    包括楼梯也要大一点,深一点,陡一点。

    据说是被当年八国联军用刀桶破的,他们是得有多闲呀。同时发现的还有原来我相机的光圈手动只有三个档。

    本想拍一个360度全景把25个鼓都放进来,可是转的时候不是碰到柱子就是碰到人,就作罢了,不过看这个鼓的成色也不像是古董。

    下楼就到了被美国副总统作秀过的姚记炒肝。

    要说美国人实在是太会作秀了,来了这么个排队打饭和食堂一样的地方作秀,用心太险恶了。

    排了半天队终于等到了传说中的炒肝和卤煮,口味还是略微有点重,可能不是每个人都喜欢,不过我吃的相当high,有阵子没这么尽兴的吃东西了。炒肝的汤很奇特貌似是冻做的,缺点就是肝有点少。我和坐在对面的老奶奶一边吃一边吐槽,这么贵的东西放肝放的这么少,我吃了一堆肠子杂碎才捞到两片肝。当然也算不上太贵,毕竟这一碗就5块,卤煮的味道还是蛮鲜的。这里的包子听说也不错,不过我吃不动了,菜单上还有一堆没听说过的特色小吃,猎奇的吃货可以考虑来尝尝,价格还算说的过去。今天胡吃一顿,估计回去又要被神医骂了。

    如果说现代化对古迹的破坏是处于一种无奈,那么还有一种破坏就让人很无语了。

    有时甚至能产生一种搞笑的效果。

    不过还是看到一个僧人在这种诡异的气氛下研究武功秘籍。

    逛着逛着就到了后海,不过我也没啥找酒吧的欲望,时间点也不太对,我还是继续偷拍吧。

    看样子这里的水应该还是很干净的。

    我总感觉两位大妈不是在下棋,是在练功。

    现在看看如果是一个老实的小正太的话还是可以接受的。

    当然我还是更羡慕这个老爹。

    在人群中发现个神秘的小美女,说什么也不把伞拿开。

    原来她是不好意思了。

    走着走着就又进入了城市。

    </embed>

    Published: 26 May 2012