关于作者

用户名:goflyfreely
笔名:goflyfreely
地区:
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



访问统计:
文章个数:10
评论个数:8
留言条数:1




Powered by BlogDriver 2.1

goflyfreely的博客

 

欢迎访问goflyfreely的博客,希望你在这里得到些许快乐!

文章

编译原理学习导论
编译原理学习导论
steveno 发表于 2005-8-13 10:13:00
大学课程为什么要开设编译原理呢?这门课程关注的是编译器方面的产生原理和技术问题,似乎和计算机的基础领域不沾边,可是编译原理却一直作为大学本科的必修课程,同时也成为了研究生入学考试的必考内容。编译原理及技术从本质上来讲就是一个算法问题而已,当然由于这个问题十分复杂,其解决算法也相对复杂。我们学的数据结构与算法分析也是讲算法的,不过讲的基础算法,换句话说讲的是算法导论,而编译原理这门课程讲的就是比较专注解决一种的算法了。在20世纪50年代,编译器的编写一直被认为是十分困难的事情,第一Fortran的编译器据说花了18年的时间才完成。在人们尝试编写编译器的同时,诞生了许多跟编译相关的理论和技术,而这些理论和技术比一个实际的编译器本身价值更大。就犹如数学家们在解决著名的哥德巴赫猜想一样,虽然没有最终解决问题,但是其间诞生不少名著的相关数论。

推荐参考书

虽然编译理论发展到今天,已经有了比较成熟的部分,但是作为一个大学生来说,要自己写出一个像Turboc C,Java那样的编译器来说还是太难了。不仅写编译器困难,学习编译原理这门课程也比较困难。

正是因为编译原理学习相对困难,那么就要求有好的教师和好的教材。教师方面不是我们能自己更改的,而在教材方面我们却可以按自己的意愿来阅读。我下面推荐几本好的编译原理的教材。我推荐的书籍都是国外的经典教材,因为在国内的教材中,确实还没发现什么让人满意的。

第一本书的原名叫《Compilers Principles,Techniques,and Tools》,另外一个响亮的名字就是龙书。原因是这本书的封面上有条红色的龙,也因为獗臼樵诒嘁朐砘×煊蛉肥堤忻?所以很多国外的学者都直接取名为龙书。最近机械工业出版社已经出版了此书的中文版,名字就叫《编译原理》。该书出的比较早,大概是在85或86年编写完成的,作者之一还是著名的贝尔实验室的科学家。里面讲解的核心编译原理至今都没有变过,所以一直到今天,它的价值都非凡。这本书最大的特点就是一开始就通过一个实际的小例子,把编译原理的大致内容罗列出来,让很多编译原理的初学者很快心里有了个底,也知道为什么会有这些理论,怎么运用这些理论。而这一点是我感觉国内的教材缺乏的东西,所以国内的教材都不是写给愿意自学的读者,总之让人看了半天,却不知道里面的东西有什么用。

第二本书的原名叫《Modern Compiler Design》,中文名字叫做《现代编译程序设计》。该书由人民邮电出版社所出。此书比较关注的是编译原理的实践,书中给出了不少的实际程序代码,还有很多实际的编译技术问题等等。此书另外一个特点就是其“现代”而字。在传统的编译原理教材中,你是不可能看到如同Java中的“垃圾回收”等算法的。因为Java这样的解释执行语言是在近几年才流行起来的东西。如果你想深入学习编译原理的理论知识,那么你肯定得看前面那本龙书,如果你想自己动手做一个先进的编译器,那么你得看这本《现代编译程序设计》。

第三本书就是很多国内的编译原理学者都推荐的那本《编译原理及实践》。或许是这本书引入国内比较早吧,我记得我是在高中就买了这本书,不过也是在前段时间才把整本书看完。此书作为入门教程也的确是个不错的选择。书中给出的编译原理讲解也相当细致,虽然不如前面的龙书那么深入,但是很多地方都是点到为止,作为大学本科教学已经是十分深入了。该书的特点就是注重实践,不过感觉还不如前面那本《现代编译程序设计》的实践味道更重。此书的重点还是在原理上的实践,而非前面那本那样的技术实践。《编译原理及实践》在讲解编译原理的各个部分的同时,也在逐步实践一个现代的编译器Tiny C.等你把整本书看完,差不多自己也可以写一个Tiny C了。作者还对Lex和Yacc这两个常用的编译相关的工具进行了很详细的说明,这一点也是很难在国内的教材中看到的。

推荐了这三本教材,都有英文版和中文版的。很多英文好的同学只喜欢看原版的书,不我的感觉是这三本书的翻译都很不错,没有必要特别去买英文版的。理解理论的实质比理解表面的文字更为重要。

编译原理的实质

前面已经说过,学习编译原理其实也就是学习算法而已,没什么特别的。只不过这些算法的产生已经形成了一套理论。下面我来看看编译原理里面到底有什么高深的理论吧。

几乎每本编译原理的教材都是分成词法分析,语法分析(LL算法,递归下降算法,LR算法),语义分析,运行时环境,中间代码,代码生成,代码优化这些部分。其实现在很多编译原理的教材都是按照85,86出版的那本龙书来安排教学内容的,所以那本龙书的内容格式几乎成了现在编译原理教材的定式,包括国内的教材也是如此。一般来说,大学里面的本科教学是不可能把上面的所有部分都认真讲完的,而是比较偏重于前面几个部分。像代码优化那部分东西,就像个无底洞一样,如果要认真讲,就是单独开一个学期的课也不可能讲得清楚。所以,一般对于本科生,对词法分析和语法分析掌握要求就相对要高一点了。

词法分析相对来说比较简单。可能是词法分析程序本身实现起来很简单吧,很多没有学过编译原理的人也同样可以写出各种各样的词法分析程序。不过编译原理在讲解词法分析的时候,重点把正则表达式和自动机原理加了进来,然后以一种十分标准的方式来讲解词法分析程序的产生。这样的做法道理很明显,就是要让词法分析从程序上升到理论的地步。

语法分析部分就比较麻烦一点了。现在一般有两种语法分析算法,LL自顶向下算法和LR自底向上算法。LL算法还好说,到了LR算法的时候,困难就来了。很多自学编译原理的都是遇到LR算法的理解成问题后就放弃了自学。其实这些东西都是只要大家理解就可以了,又不是像词法分析那样非得自己写出来才算真正的会。像LR算法的语法分析器,一般都是用工具Yacc来生成,实践中完全没有比较自己来实现。对于LL算法中特殊的递归下降算法,因为其实践十分简单,那么就应该要求每个学生都能自己写。当然,现在也有不少好的LL算法的语法分析器,不过要是换在非C平台,比如Java,Delphi,你不能运用YACC工具了,那么你就只有自己来写语法分析器。

等学到词法分析和语法分析时候,你可能会出现这样的疑问:“词法分析和语法分析到底有什么?”就从编译器的角度来讲,编译器需要把程序员写的源程序转换成一种方便处理的数据结构(抽象语法树或语法树),那么这个转换的过程就是通过词法分析和语法分析的。其实词法分析并非一开始就被列入编译器的必备部分,只是我们为了简化语法分析的过程,就把词法分析这种繁琐的工作单独提取出来,就成了现在的词法分析部分。除了编译器部分,在其它地方,词法分析和语法分析也是有用的。比如我们在DOS,Unix,Linux下输入命令的时候,程序如何分析你输入的命令形式,这也是简单的应用。总之,这两部分的工作就是把不“规则”的文本信息转换成一种比较好分析好处理的数据结构。那么为什么编译原理的教程都最终把要分析的源分析转换成“树”这种数据结构呢?数据结构中有Stack, Line,List…这么多数据结构,各自都有各自的特点。但是Tree这种结构有很强的递归性,也就是说我们可以把Tree的任何结点Node提取出来后,它依旧是一颗完整的Tree。这一点符合我们现在编译原理分析的形式语言,比如我们在函数里面使用函树,循环中使用循环,条件中使用条件等等,那么就可以很直观地表示在Tree这种数据结构上。同样,我们在执行形式语言的程序的时候也是如此的递归性。在编译原理后面的代码生成的部分,就会介绍一种堆栈式的中间代码,我们可以根据分析出来的抽象语法树,很容易,很机械地运用递归遍历抽象语法树就可以生成这种指令代码。而这种代码其实也被广泛运用在其它的解释型语言中。像现在流行的Java,.NET,其底层的字节码bytecode,可以说就是这中基于堆栈的指令代码的。

关于语义分析,语法制导翻译,类型检查等等部分,其实都是一种完善前面得到的抽象语法树的过程。比如说,我们写C语言程序的时候,都知道,如果把一个浮点数直接赋值给一个整数,就会出现类型不匹配,那么C语言的编译器是怎么知道的呢?就是通过这一步的类型检查。像C++语言这中支持多态函数的语言,这部分要处理的问题就更多更复杂了。大部编译原理的教材在这部分都是讲解一些比较好的处理策略而已。因为新的问题总是在发生,旧的办法不见得足够解决。

本来说,作为一个编译器,起作用的部分就是用户输入的源程序到最终的代码生成。但是在讲解最终代码生成的时候,又不得不讲解机器运行环境等内容。因为如果你不知道机器是怎么执行最终代码的,那么你当然无法知道如何生成合适的最终代码。这部分内容我自我感觉其意义甚至超过了编译原理本身。因为它会把一个计算机的程序的运行过程都通通排在你面前,你将来可能不会从事编译器的开发工作,但是只要是和计算机软件开发相关的领域,都会涉及到程序的执行过程。运行时环境的讲解会让你更清楚一个计算机程序是怎么存储,怎么装载,怎么执行的。关于部分的内容,我强烈建议大家看看龙书上的讲解,作者从最基本的存储组织,存储分配策略,非局部名字的访问,参数传递,符号表到动态存储分配(malloc,new)都作了十分详细的说明。这些东西都是我们编写平常程序的时候经常要做的事情,但是我们却少去探求其内部是如何完成。

关于中间代码生成,代码生成,代码优化部分的内容就实在不好说了。国内很多教材到了这部分都会很简单地走马观花讲过去,学生听了也只是作为了解,不知道如何运用。不过这部分内容的东西如果要认真讲,单独开一学期的课程都讲不完。在《编译原理及实践》的书上,对于这部分的讲解就恰到好处。作者主要讲解的还是一种以堆栈为基础的指令代码,十分通俗易懂,让人看了后,很容易模仿,自己下来后就可以写自己的代码生成。当然,对于其它代码生成技术,代码优化技术的讲解就十分简单了。如果要仔细研究代码生成技术,其实另外还有本叫做《Advance Compiler Desgin and Implement》,那本书现在由机械工业出版社引进的,十分厚重,而且是英文原版。不过这本书我没有把它列为推荐书给大家,毕竟能把龙书的内容搞清楚,在中国已经就算很不错的高手了,到那个时候再看这本《Advance Compiler Desgin and Implement》也不迟。代码优化部分在大学本科教学中还是一个不太重要的部分,就是算是实践过程中,相信大家也不太运用得到。毕竟,自己做的编译器能正确生成执行代码已经很不错了,还谈什么优化呢?

关于实践

编译原理的课程毕竟还只是讲解原理的课程,不是专门的编译技术课程。这两门课程是有很大的区别的。编译技术更关注实际的编写编译器过程中运用到的技术,而原理的课关注讲解其基本理论。但是计算机科学本身就是一门实践性很强的课程,如果能够学以致用,那才叫真正的学会。李阳在讲解疯狂英语的时候就说到,只要当你会实际中运用一个单词一个词组的时候你才能叫学会了这个单词或者词组,而不是只是知道了它的拼写和意思。其实任何学习都是一样的,如果缺少了实践的结合,你不能算学会。

编译原理的课程主要就是讲解编译器产生的理论和原理,那么很简单,自己写个编译器就是最好的实践过程了。不过你得小心,编译系统可能是所有软件系统中最复杂的系统之一,不然为什么大学里面还会把编译器的编写开成一门叫做编译原理的课程来讲?我很佩服那些学了操作系统原理就开始自己写操作系统,学了编译原理就开始自己写编译器的人们,确实,在中国,敢这么做的学生太少了。且不管你这样做能不能做成功,至少有了这个尝试,会让你的程序设计,系统规划安排的功底增进不少。我下面给出一些关于实践过程中可能会遇到的困难,希望能够在你陷入困境的前帮你一把。

1. Lex和Yacc. 这两工具是作为词法分析很语法分析的工具。如果你自己写一个编译器,我十分不建议你连词法分析这种事情都亲手来写。Lex和Yacc应该是作为每本编译原理的教材的必备内容,可是在国内的教材中缺很少看到。这两个工具是Unix系统下的小东西,如果你要在Windows中运用,那么你最好去下在cygwin这个软件。它是个在Windows下模拟Unix的东东,里面就包含了flex.exe和bison.exe(yacc)这两个工具.这两个工具使用起来还挺麻烦的(其实unix 下的很多十分有用的工具都是这样), 不过在《编译原理与实践》这本书上对于这两个工具的讲解十分详细,还列举了不少实际的例子。

2. 做解释型语言比做生成机器代码的编译器简单。虽然说,做解释型的编译器,像Java那样的,你还得自己去写解释器,不过这样你就不必去查找机器代码的资料了。如果你做生成的最终机器代码编译器可能会遇到问题还有就是寄存器为基础的代码生成方法。前面说过,如果你生成的是以堆栈为基础的代码,那么其代码生成过程十分简单,需要考虑的东西也不多,如果你考虑最终的机器代码生成的话,你必须考虑机器的寄存器如何分配等麻烦的问题。

3. 考虑用别人已经生成的语法文件,尽量不要自己动手写词法文件和语法文件.以前一个朋友曾经说过,写出一个好的程序语言的语法定义,就几乎完成了一个编译器的一半.确实是这样,语法文件的编写是个很难的事情.现在网上到处都可以找到比如C语言,C++,Java, Tiny C,Minus C等语言的词法文件和语法文件,你完全可以自己下下来来用.

在《编译原理及实践》的书中,作者给出了一个Tiny C的全部代码.我自我感觉作者的这个编译器做得很不错,相对于其它php,perl等语言的源代码来说,简单得多,容易看懂,而且很清晰地展现了一个完成的编译系统的实现过程.其源代码可以在作者的网站上下载.

后话

编译原理的学习可能算是一个困难的历程,特别是对于那些不对编译系统感兴趣的同学来说.既然它已经作为了大学本科的必修课程,那么就说明的它引申出来的一套理论在整个计算机科学领域还是占有相对重要的地位.

如果我们考究一下历史,就会发现很多被称为程序设计大师的人都是编译领域的高手.写出第一个微型机上运行的Basic语言的比尔盖茨,设计出Delphi的Borland的”世界上最厉害的程序员”, Sun的J***A之父, 贝尔实验室的C++之父…

- 作者: goflyfreely 2005年11月6日, 星期日 21:58  回复(4) |  引用(1) 加入博采

Eclipse的linux安装
Eclipse是一由IBM,Borland等资助的开源开发环境;其功能可以通过插件方式进行扩展;本文在Linux下构建Java、C、C++的IDE。

我用的环境是 Redhat Linux 9 (自编译Gnome2.4)

一.下载所需软件(所有下载的软件均放在/opt下)

先下载Eclipse,网址为http://www.eclipse.org,目前,Eclipse的最新版本為2.1.1,3.0版也正在测试中。我使用eclipse2.1;下载其gtk版本:eclipse-SDK-2.1.1-linux-gtk.zip

执行 Eclipse是须用到JDK,但Eclipse的安装程序和Red Hat Linux 9 里没有包含JDK,Sun 最新版本的 JDK可到http://java.sun.com下载,在此我们使用的是Sun jdk(J2SE) 1.4.2_01版(也可使用IBM的jdk)。

要在Eclipse 上面开发C/C++程序,需要另外安装plug-ins,在此我们使用的是C/C++ Development Tools(CDT)。CDT 整合了gcc、make、gdb等GUN 工具,(CDT 与Eclipse 中内建的JDT(Java 开发环境)比起来,功能还差得远。例如,在JDT 中相当好用的Refactor、Refactoring、Organize Imports等在CDT中都没有。)CDT 可从http://www.eclipse.org/cdt/ 下载,目前最新版本为CDT 1.1 GA2 .

二.安装

1.由于CDT需要gcc等工具,所以要先把Redhat9的软件开发包装上。

2.安装JDK(需以root身份安装):

[root@redarmy] chmod +x j2sdk-1_4_2_01-linux-i586-rpm.bin
[root@redarmy] ./j2sdk-1_4_2_01-linux-i586-rpm.bin
[root@redarmy] rpm –ivh j2sdk-1_4_2_01-linux-i586-rpm.bin

安装好的JDK 会存在 /usr/java/j2sdk1.4.2_01 目录中。设定JAVA_HOME,CLASSPATH,PATH; 在/etc/profile文件最后加如下四行:

export JAVA_HOME = /usr/java/j2sdk1.4.2_01
export PATH = $JAVA_HOME/bin:$PATH
CLASSPATH=.:/usr/java/j2sdk1.4.2_01/lib/tools.jar:$CLASSPATH
export CLASSPATH

3.安裝Eclipse
在此我把Eclipse安装在/opt下,安装Eclipse很简单,只要把下载回来的压缩包解压就可以了;解压后得到Eclipse目录;

[root@redarmy] unzip –d /opt eclipse-SDK-2.1.1-linux-gtk.zip

为让每一个帐号都可以执行Eclipse,我写了个小脚本(Eclipse.sh):

#!/bin/bash
#
# 执行 eclipse 2.1.1
#
export JAVA_HOME=/usr/java/j2sdk1.4.2_01
export CLASSPATH=/usr/java/j2sdk1.4.2_01/lib
/opt/eclipse/eclipse -vm /usr/java/j2sdk1.4.2_01/bin/java -data ~/workspace &
# -vm 参数用以指定使用哪一个 jvm 来执行Eclipse,
# -date参数用以指定Eclipse的数据目录。在此指定其存在用户根目录(~)下的workspace目录中
 


将eclipse.sh 复制到/usr/local/bin中,并为它加上权限755;现在执行 eclipse.sh 即可启动 Eclipse。

[root@redarmy] cp eclipse.sh /usr/local/bin

[root@redarmy] chmod 755 /usr/local/bin/eclipse.sh

将Eclipse添加到桌面。首先,在桌面上按下鼠标右键,在弹出菜单中选择“新增启动”,之后分別在“名称”中输入Eclipse、“命令”中填/usr/local/bin/eclipse.sh,然后再为它随便找个喜欢的图标(我用的是/opt/eclipse/icon.xpm);再后按“确定”,桌面上就有eclipse的快捷方式了,以后可以直接双击这个图标启动Eclipse。

Eclipse 安装好后,已经内建了java开发环境(JDT)就可以直接开发Java 程序。

4.安装CDT,CDT 1.1 GA 目前只支持Eclipse 2.1 版。

将下载的包解压,会得到features 和plugins 这两个目录

[root@redarmy] unzip –d /opt org.eclipse.cdt-linux.gtk_1.1.0.bin.dist.zip

分别将这两个目录中的所有文件分别剪到/opt/eclipse下的对应目录里,即可。(Eclipse的插件安裝方法几乎都这样安装: 把文件下载后, 直接解到Eclipse所安装的目录中对应的features 和plugins 中即可。)

三.程序实例

这没多少好说的,对C、C++开发,都是先写源程序,再写个makefile。

四:附

要是不习惯,Eclipse英文环境,可以在Eclipse.org的主站上下,它的语言包;装了语言包后,不光菜单成中文了,它的帮助文档也成中文了。


- 作者: goflyfreely 2005年10月24日, 星期一 11:41  回复(0) |  引用(1) 加入博采

linux编译内核的文章(转载:深刻感谢写此文的人)
*以下步骤有很多都是很初级的命令或解释,因为偶是linux新手,
*在编译过程中走了很多弯路,花了大量时间找各种解决办法,所以
*把相应的命令都写了出来,希望对跟偶一样的才入门不久而又想
*编译内核的新手有所帮助!
*
* kilvon 05-Mar-2003
**********************************************************************

基本编译情况说明:偶目前的版本是: RedHat linux 8.0
(机器有双操作系统:linux和windows 2000)
内核版本是 2.4.18-14,硬件是笔记本compaq 的某一型号,
下载的内核版本是2.4.20(在
www.kernel.org上可以找到),
推荐编译内核时使用高版本,而不是在以前的版本上编译,
原因见第7.1步的说明

在编译开始前,建议先在windows下用相关软件对硬件做一个
详细统计,包括硬件类型,厂家,芯片版本等等,特别是笔记本
和品牌机,因为二者很多部件都是OEM其它厂家的,并把它打印
出来以供配置内核时使用.(linux下也可以用:系统工具->
硬件浏览器来查看)

另外建议在身旁准备几张纸和笔,随时把你认为重要的信息记下来,
当然包括错误信息了,以帮助以后判断和解决问题.

1.将内核源码包linux-2.4.20.tar.bz2 copy至/usr/src目录下:
#cp linux-2.4.20.tar.bz2 /usr/src
#cd /usr/src

2.将指向以前内核版本的symbol link删除
#rm -f linux-2.4

3.用以下命令解开压缩包
#bzip2 -d linux-2.4.20.tar.bz2
#tar -xvf linux-2.4.20.tar

4.创建新的symbol link以链接到刚解开的源码所在目录
#ln -s linux-2.4.20 linux-2.4

5.进入到以后编译时用的工作目录虾:
#cd /usr/src/linux-2.4

6.该命令保证源代码目录下没有不正确的.o文件(即object文件,编译c语
言时生成的,目的是下一步编译成可执行码时link之用)以及文件的相互
倚赖关系.第一次编译刚下载的源码包不用此命令,但如果多次使用这
些源码编译内核,那么一定要先运行本命令.
#make mrproper

7.为了不影响已经可用的内核(比如安装linux时装入的内核),现在需要
保存以前的可用的内核(以使得编译失败仍然可以"方便的"启动linux),
并且我们要对本次编译的内核标识一个容易辨认的标记,以下几步与
编译暂时无关.

7.1偶使用grub作为boot manager,所以要修改grub.conf文件,
#cp /boot/grub/grub.conf /boot/grub/grub.conf.bck
(建议有条件打印一份原始的grub.conf文件,原因见第7.4步)
#emacs /boot/grub/grub.conf
(emacs小提示: ctrl+ x +s 为保存结果,ctrl + x +c为关闭emacs,
删除n行文字为:先把光标放在要删除文字的起始处 ctrl + u,然后敲入要
删除的行数,比如4,最后ctrl + k)

下面是偶的grub.conf内容:
default=1
timeout=10
splashimage=(hd0,6)/grub/splash.xpm.gz
title Psyche (2.4.18-14 standard)
root (hd0,6)
kernel /vmlinuz-2.4.18-14.standard ro root=/dev/hda8
initrd /initrd-2.4.18-14.standard.img
title Windows 2000
rootnoverify (hd0,0)
chainloader +1

注意kernel...和initrd...两条语句,因为要与以下改动对应:
#rm -f /boot/System.map
#rm -f /boot/vmlinuz
#cp /boot/System.map-2.4.18-14 /boot/System.map-2.4.18.standard
#ln -s /boot/System.map-2.4.18.standard /boot/System.map
#cp /boot/vmlinuz-2.4.18-14 /boot/vmlinuz-2.4.18-14.standard
#ln -s /boot/vmlinuz-2.4.18-14.standard /boot/vmlinuz
#cp /boot/initrd-2.4.18-14.img /boot/initrd-2.4.18-14.standard.img
(initrd只用了copy,因为偶是编译一个高版本的内核,而不是同一个版本
内核的重新编译,编译高版本的好处在于系统会建立另外的目录而不会
用新编译的(可能是错的)版本覆盖以前的版本,看一下/lib/modules目录
就明白了.)

7.2如何知道你的根目录"\"在哪个partition上? 命令为:
#df
以下是偶机器的部分输出:
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda8 4137264 2136592 1790508 55% /
...

看看你的系统根目录装在哪里很重要,因为后面你将会看到系统安装编译好的内核时在grub.conf插入的命令中root=LABEL=/ hdc=ide-scsi
可能会引发系统引导时的如下错误:
VFS: Cannot open root device "" or 00:00
Please append a correct "root=" boot option
Kernel panic: VFS: Unable to Mount root fs on 00:00
所以要在grub.conf里修改其命令为:root=/dev/hda8

7.3好了,做完这些准备工作后,我们要--
重启一下机器,不要急,应为要先确认7.1步的工作的正确性,以免把7.1错误
带入以后的步骤中.(编译内核一定要非常小心谨慎,不能急躁,否则,嘿嘿...)

7.4如果在重启过程中系统有问题,可以在grub的引导界面上临时改动grub引
导参数,相关命令有:
e -编辑引导命令
ESC键 -回到上级目录
o -插入一行命令
b -开始引导系统
d -删除一行
其实你可以把grub控制台上的命令都删了(只影响本次启动),然后按照
/boot/grub/grub.conf里的命令手工在grub控制台上敲进去,也是一样的效果.

7.5如果你能使用重新配置的grub命令正确启动系统,那么让我们开始真正的
编译工作吧!!!!

7.6先保证我们在编译的工作目录下:
#cd /usr/src/linux-2.4
然后编辑Makefile(这个文件是用来控制编译用的),找到这一行:
EXTRAVERSION =
修改为(以偶本次编译为例,也可以是任意的合法字符串,比如"-sema-v.4")
EXTRAVERSION = -kilvon.001

8.偶是在X Window下编译:
#make xconfig

8.1如果你是在文本模式下,用
#make menuconfig

8.2其实编译步骤里最难的就是内核参数的配置,我在这里耗费了很多时间,
更惨的是开始并没有认识到这一点,以为是那些命令的使用...所以,接着看吧:


8.3选择的原则是将与内核其它部分关系较远且不经常使用的部分功能代码编译成为可加载模块(哪些较远?看各人对linux和操作系统概念的理解程度了, 还有就是看所配置项的help),有利于减小内核的长度,减小内核消耗的内存,简化该功能相应的环境改变时对内核的影响;不需要的功能就不要选;与内核关心紧密而且经常使用的部分功能代码直接编译到内核中。下面对常用的选项分别加以介绍:

/1. Code maturity level options
代码成熟等级。此处只有一项:
prompt for development and/or incomplete code/drivers
如果你要试验现在仍处于实验阶段的功能,比如khttpd、IPv6等,就必须
把该项选择为Y了;否则可以把它选择为N。

/2. Loadable module support
对模块的支持。这里面有三项:

Enable loadable module support:
除非你准备把所有需要的内容都编译到内核里面,否则该项应该是必选的。
Set version information on all module symbols:
可以不选它。
Kernel module loader:
让内核在启动时有自己装入必需模块的能力,建议选上。

/3. Processor type and features
CPU类型,选项很多,不一一介绍了,有关的几个如下:

Processor family:
根据你自己的情况选择CPU类型。
High Memory Support:
大容量内存的支持。可以支持到4G、64G,一般可以不选。
Math emulation:
协处理器仿真,协处理器是在386时代的宠儿,现在早已不用了。
MTTR support:MTTR支持。可不选。
Symmetric multi-processing support:
对称多处理支持。除非你富到有多个CPU,否则就不用选了。

/4. General setup
这里是对最普通的一些属性进行设置。这部分内容非常多,一般使用缺省设置就可以了。下面介绍一下经常使用的一些选项:

Networking support:
网络支持,必须选,没有网卡也建议选上。
PCI support:
PCI支持,必选.
PCI access mode:
PCI存取模式。可供选择的有BIOS、Direct和Any,选Any吧。
Support for hot-pluggabel devices:
热插拔设备支持,可选.
PCMCIA/CardBus support:
PCMCIA/CardBus支持,有PCMCIA就必选了。
System V IPC
BSD Process Accounting
Sysctl support:
以上三项是有关进程处理/IPC调用的,主要就是System V和BSD两种风格。
如果你不是使用BSD,就按照缺省吧。
Power Management support:电源管理支持,可选上,特别是笔记本.
Advanced Power Management BIOS support:高级电源管理BIOD支持。

/5. Memory Technology Device(MTD)
MTD设备支持
可不选。

/6. Parallel port support
串口支持。如果不打算使用串口,就别选了。

/7. Plug and Play configuration
即插即用支持。选上吧,可以体验一下Linux下即插即用的感觉。

/8. Block devices
块设备支持,需要针对每个人的具体情况来选:

Normal PC floppy disk support:普通PC软盘支持,一般要选,我的没有,
就没选
XT hard disk support:
Compaq SMART2 support:
Mulex DAC960/DAC1100 PCI RAID Controller support:RAID镜像用的。
Loopback device support:
Network block device support:网络块设备支持。如果想访问网上邻居的
东西,就选上。
Logical volume manager(LVM)support:逻辑卷管理支持。
Multiple devices driver support:多设备驱动支持。
RAM disk support:RAM盘支持。

/9. Networking options
网络选项。这里配置的是网络协议。自己看吧.
除了肯定要选中TCP/IP networking外,其它看着办吧

/10. Telephony Support
Linux下可以支持电话卡,这样你就可以在IP上使用普通的电话提供语音服务.详细情况可看看help内容.

/11. ATA/IDE/MFM/RLL support
这个是有关各种接口的硬盘/光驱/磁带/软盘支持的,内容太多了,使用缺省
的选项吧,偶有PCMCIA卡,各人机器情况不一样.

/12. SCSI support
SCSI设备的支持, 如果你用了SCSI的硬盘/光驱/磁带等设备,自己找好了.

/13. IEEE 1394(FireWire)support
偶的是灰的,不用操心了,)

/14. I2O device support
在智能Input/Output(I2O)体系接口中使用,不会,用缺省吧.

/15. Network device support
网络设备支持。上面选好协议了,现在该选设备.
为了免得麻烦,编译到内核里面好了,不选M了,选Y。耐心点,一般说来你都能找到自己用的网卡。如果没有,你只好自己到厂商那里去当驱动了,
或者去
www.mydrivers.com看看

/16. Amateur Radio support
没有,不选.

/17. IrDA(infrared)support
这个要红外支持,我的有.

/18. ISDN subsystem
如果你使用ISDN上网,这个就必不可少了

/19. Old CD-ROM drivers(not SCSI、not IDE)
专门为非SCSI/IDE口的光驱做的,但谁还在用那么老的东东啊,自己选吧.

/20.Input Core Support
这个选项很重要,除了joystick(游戏遥控杆)建议都选"m".切记!

/21. Character devices
字符设备。这个内容又太多了,先使用缺省设置,需要的话自己就修改:

I2C support:I2C是Philips极力推动的微控制应用中使用的低速串行
总线协议。如果你要选择下面的Video For Linux,该项必选。
Mice:鼠标。如果是笔记本,建议在Bus Mouse Support选上"y".
Joysticks:手柄。即使在Linux下把手柄驱动起来意义不大
Watchdog Cards:虽然称为Cards,这个可以用纯软来实现,当然也有
硬件的。如果你把这个选中,那么就会在你的/dev下创建一个名为
watchdog的文件,它可以记录你的系统的运行情况,一直到系统重新
启动的1分钟左右。有了这个文件,你就可以恢复系统到重启前的状态了。
Video For Linux:支持有关的音频/视频卡。
Ftape, the floppy tape device driver:
PCMCIA character device support:

/22.Multimedia devices
为捕捉audio/video用,如果感兴趣看看help

/23. File systems
文件系统。内容太多了,建议在缺省选项的基础上进行修改。
介绍以下几项:

Quota support:Quota可以限制每个用户可以使用的硬盘空间的上限,在多用户共同使用一台主机的情况中十分有效。
DOS FAT fs support:

DOS FAT文件格式的支持,可以支持FAT16、FAT32。
ISO 9660 CD-ROM file system support:光盘使用的就是ISO 9660的文件格式。
NTFS file system support:ntfs是NT使用的文件格式,你要在linux下mount ntfs分区的话,就要选上它。记得在mount的时候,

只有iocharset=cp936可以加上,codepage=936不能加。
/proc file system support:/proc文件系统是Linux提供给用户和系统进行交
互的通道,建议选上,否则有些功能没法正确执行。

还有另外三个大类都规到这儿了:Network File Systems(网络文件系统)、
Partition Types(分区类型)、Native Language Support(本地语言支持)。
值得一提的是Network File Systems里面的两种:NFS和SMB分别是Linux和
Windows相互以网络邻居的形式访问对方所使用的文件系统,根据需要加以选择。

/24 Console drivers
用缺省

/25 Sound
你用什么声卡?选选吧.

/26 USB Support
很重要,至少要选以下选项
Support for USB
UCHI Alternate Deriver (JE) Support
OCHI (Compaq,iMacs...
USB Audio...
USB MIDI...
USB Human Interface Device (full HID) support
HID input layer support
/dev/hiddev raw HID...
USB LCD device support
因为偶的硬件很多都要求USB HID 支持,所以这里选了不少

*如果有某些选项那不准,可以参考:
/usr/src/linux-2.4/Documentation/Configure.help
也可以search整个系统并看看相关的文字都在哪些文件出现:
#find /usr -name "*.*" -print -exec grep
-q -s mousedev {} \; -print
这个长命令很有用

8.4别忘了将你的配置保存到一个文件里,否则下次编译时又要重选!
Load Configuration from file
比如保存到/home/kilvon/conf/Kernel-kilvon.001

8.5用以下命令读取刚才的配置数据使之生效:
#make dep
#make clean

9.开始编译内核和模块
#make bzImage
#make modules
#make modules_install

10.将编译好的文件移到/boot下;如果上面某步有错,大部分情况是由于
配置内核选项时将一些当前版本只能编译为modules的选为编译到内核里,
我遇到好几次这样的情况.应为既然
www.kernel.org发布一个稳定的内核,
(偶没down那些alpha,beta版)9成9可以成功的编译.
#move /usr/src/linux-2.4/System.map /boot/System.map-2.4.20-kilvon.001
#move /usr/src/linux-2.4/arch/i386/boot/bzImage
/boot/vmlinuz-2.4.20-kilvon.001
#rm -f System.map
#rm -f vmlinuz
#ln -s /boot/System.map-2.4.20-kilvon.001 /boot/System.map
#ln -s /boot/vmlinuz-2.4.20-kilvon.001 /boot/vmlinuz

11.作些收尾工作:
#new-kernel-pkg --install --depmod --mkinitrd 2.4.20-kilvon.001
--mkinitrd 作Initial Ramdisk的,可以直接敲个mkinitrd -h看看
--depmod 检查内核中有没有未解析的symbol
--install 在grub中安装一个启动选项

12.看看第7.2步的相关解释,现在请修改/boot/grub/grub.conf文件,
以下是修改后的grub.conf:
default=2
timeout=10
splashimage=(hd0,6)/grub/splash.xpm.gz
title Psyche (2.4.20-kilvon.001)
root (hd0,6)
kernel /vmlinuz-2.4.20-kilvon.001 ro root=/dev/hda8
initrd /initrd-2.4.20-kilvon.001.img
title Psyche (2.4.18-14 standard)
root (hd0,6)
kernel /vmlinuz-2.4.18-14.standard ro root=LABEL=/ hdc=ide-scsi
initrd /initrd-2.4.18-14.standard.img
title Windows 2000
rootnoverify (hd0,0)
chainloader +1

13.再好好检查一下/boot下的文件名是否敲对了(前面有好多的mv,cp动作)
[root@localhost boot]# ll
total 8880
5824 9月 6 04:53 boot.b
612 9月 6 04:53 chain.b
42150 9月 5 01:47 config-2.4.18-14
1024 3月 5 21:32 grub
130983 3月 5 03:49 initrd-2.4.18-14.img
130983 3月 4 20:21 initrd-2.4.18-14.standard.img
65499 3月 5 21:31 initrd-2.4.20-kilvon.001.img
473 3月 5 03:49 kernel.h
12288 3月 5 03:44 lost+found
23108 9月 6 22:05 message
21282 9月 6 22:05 message.ja
21 3月 5 03:49 module-info -> module-info-2.4.18-14
15436 9月 5 01:47 module-info-2.4.18-14
15436 3月 4 20:21 module-info-2.4.18.standard
16834 3月 5 21:17 MyKernelSetup-kilvon.001
640 9月 6 04:53 os2_d.b
28 3月 5 19:32 System.map -> System.map-2.4.20-kilvon.001
507814 9月 5 01:47 System.map-2.4.18-14
507814 3月 4 20:20 System.map-2.4.18-14.standard
588175 3月 5 21:24 System.map-2.4.20-kilvon.001
3236438 9月 5 01:47 vmlinux-2.4.18-14
31 3月 5 12:51 vmlinuz -> /boot/vmlinuz-2.4.20-kilvon.001
1125194 9月 5 01:47 vmlinuz-2.4.18-14
1125194 3月 4 20:19 vmlinuz-2.4.18-14.standard
1458790 3月 5 21:24 vmlinuz-2.4.20-kilvon.001

14.好了,来吧:
#reboot

15.如果有错无法启动,这回到grub控制台然后用以前的内核启动,还记得吗?前面第7步的"额外"工作将在这时为你节省大量时间...

16.如果系统可以启动到登录界面并可以登录,但启动过程中有Failed的项,查看:/var/log/boot.log或该目录下搜索一下,看看是什么问题,偶就遇到类似问题,
后来通过改变内核编译的配置而解决掉这些讨厌的红色文字,好了,就写到这里,已经是3月6号凌晨1点钟了,偶要睡觉了,明天还要上班.
(http://www.fanqiang.com)

- 作者: goflyfreely 2005年10月22日, 星期六 11:58  回复(0) |  引用(1) 加入博采

VC初学者的经典错误LNK2001详解
学习VC++时经常会遇到链接错误LNK2001,该错误非常讨厌,因为对于编程者来说,最好改的错误莫过于编译错误 


[正文] 
学习VC++时经常会遇到链接错误LNK2001,该错误非常讨厌,因为对于编程者来说,最好改的错误莫过于编译错误,而一般说来发生连接错误时,编译都已通过。产生连接错误的原因非常多,尤其LNK2001错误,常常使人不明其所以然。如果不深入地学习和理解VC++,要想改正连接错误LNK2001非常困难。

初学者在学习VC++的过程中,遇到的LNK2001错误的错误消息主要为:

  unresolved external symbol “symbol”(不确定的外部“符号”)。

  如果连接程序不能在所有的库和目标文件内找到所引用的函数、变量或标签,将产生此错误消息。一般来说,发生错误的原因有两个:一是所引用的函数、变量不存在、拼写不正确或者使用错误;其次可能使用了不同版本的连接库。

  以下是可能产生LNK2001错误的原因:

  一.由于编码错误导致的LNK2001

  1.不相匹配的程序代码或模块定义(.DEF)文件能导致LNK2001。例如, 如果在C++源文件内声明了一变量“var1”,却试图在另一文件内以变量“VAR1”访问该变量,将发生该错误。

  2.如果使用的内联函数是在.CPP文件内定义的,而不是在头文件内定义将导致LNK2001错误。

  3.调用函数时如果所用的参数类型同函数声明时的类型不符将会产生LNK2001。

  4.试图从基类的构造函数或析构函数中调用虚拟函数时将会导致LNK2001。

  5.要注意函数和变量的可公用性,只有全局变量、函数是可公用的。静态函数和静态变量具有相同的使用范围限制。当试图从文件外部访问任何没有在该文件内声明的静态变量时将导致编译错误或LNK2001。

  函数内声明的变量(局部变量) 只能在该函数的范围内使用。

  C++ 的全局常量只有静态连接性能。这不同于C,如果试图在C++的多个文件内使用全局变量也会产生LNK2001错误。一种解决的方法是需要时在头文件中加入该常量的初始化代码,并在.CPP文件中包含该头文件;另一种方法是使用时给该变量赋以常数。

  二.由于编译和链接的设置而造成的LNK2001

  1.如果编译时使用的是/NOD(/NODEFAULTLIB)选项,程序所需要的运行库和MFC库在连接时由编译器写入目标文件模块, 但除非在文件中明确包含这些库名,否则这些库不会被链接进工程文件。在这种情况下使用/NOD将导致错误LNK2001。

  2.如果没有为wWinMainCRTStartup设定程序入口,在使用Unicode和MFC时将得到“unresolved external on _WinMain@16”的LNK2001错误信息。

  3.使用/MD选项编译时,既然所有的运行库都被保留在动态链接库之内,源文件中对“func”的引用,在目标文件里即对“__imp__func” 的引用。如果试图使用静态库LIBC.LIB或LIBCMT.LIB进行连接,将在__imp__func上发生LNK2001;如果不使用/MD选项编
译,在使用MSVCxx.LIB连接时也会发生LNK2001。

  4.使用/ML选项编译时,如用LIBCMT.LIB链接会在_errno上发生LNK2001。

  5.当编译调试版的应用程序时,如果采用发行版模态库进行连接也会产生LNK2001;同样,使用调试版模态库连接发行版应用程序时也会产生相同的问题。

  6.不同版本的库和编译器的混合使用也能产生问题,因为新版的库里可能包含早先的版本没有的符号和说明。

  编程时打开了函数内联(/Ob1或/Ob2),但是在描述该函数的相应头文件里却关闭了函数内联(没有inline关键字),这时将得到该错误信息。为避免该问题的发生,应该在相应的头文件中用inline关键字标志内联函数。

  8.不正确的/SUBSYSTEM或/ENTRY设置也能导致LNK2001。

- 作者: goflyfreely 2005年09月11日, 星期日 18:20  回复(0) |  引用(1) 加入博采

关于宏的一些理解

宏其实和内联函数有点像,但宏不仅可以是函数也可以是一些变量.它们在头文件里定义然后在编译的时候替换调引用的宏.宏和函数相比,用宏的代码在编译后会变得大一些,但是执行起来比较快一点.函数呢虽然不会让代码变大,但是每次执行都要载入所以执行起来比较慢一些.

在定义宏的时候千万要注意空格的使用,因为很可能在替换宏的时候会把你不经意打的空格当作宏的一部分替换进去.所以不要在宏及其参数之间键入空格.

注意,作为规则一定要将宏参数放到括号内.宏和函数的另一个区别是,宏是没有类型的,然而函数都是有类型的.

#include 和#include "xxx.h"的区别

头文件放在左右尖括号当中<>,C编译气将首先在它自己的头文件子目录当中搜索指定文件.如果没找到它就搜索当前子目录或用户指定的子目录.当用户把头文件放在双引号当中的时候,编译器仅搜索当前子目录.

'A'表示字符,"A"表示字符串后面有个NULL,也就是\0.

- 作者: goflyfreely 2005年09月9日, 星期五 21:53  回复(0) |  引用(1) 加入博采

printf的用法

以前开始学编程就学的C啊,对C的库函数一点都不了解啊!一天就晓得用cout>>在哪里打印字符啊!今天看了C中printf的用法,果然很强大啊!!!!!!!!!

printf()可以有多个参数,但第一个参数必须为字符串.可以在第一个字符串中加入一些标识符标记要输其它参数的位置和类型.比如:

printf("The user is %d years old.\n",age);

其中%d就标识了参数age要显示的位置和类型.当然也可以是多个参数哈.

printf("user info:age :%d :weight %d; height  %d.\n",age,weight,height);

这里后面的参数就有顺序了哈,自己要把握了.这里%d是标识整型变量的,下面我要介绍其它类型变量当如何标识.

用%o(是字母o不是零哈)来标识八进制数,用%x和%X来标识十六进制数.x表示后面的十六进制中的X用小写,想法大写后面就是大写咯.用%u来标识无符号整型变量.用%ld来标识长整型值.用%f标识浮点数值.

用%c来标识字符型数值.这里要举两个例子

printf("The letter is %c \n",'A');

printf("The letter id %c\n",65);

上面两个例子都打印字母A.

用指数格式显示浮点数:

用%e或%E标识符.他们的区别也是大小写的问题如:1.2566e+01和1.2588E.

用%s标识符显示一个字符串.用%p标识符显示一个指针所指向向的内存地址.

如果要在数值前面加上符号,可以在%后添加一个符号.如%+d.

在%后加数字表示至少要显示的位数.如%3d,不够的用空格填充.如用前面的标识符来显示11则显示出来的效果是空格+11.当然前面填充的不一定就是空格哈.也可以用数字0来填充.%03d.显示11的时候就是011了.

用%#来要求显示前缀,比如说十六进制的0X.

当然还有其它一些规则,很多啊.

- 作者: goflyfreely 2005年09月9日, 星期五 21:00  回复(3) |  引用(1) 加入博采

C语言中的变量类型

最近重新开始学C语言了,以前觉得C++,JAVA很好啊.现在才知道了解底层的东西也是相当重要啊.醒悟了!现在开始学C!希望通过博客的方式一方面总结自己,另一方面能和各个地方的朋友们交流一下.哈哈!

C语言的变量有三种类型:char,int,float,double

其中char为字符类型的变量是八位的,最前一位作为符号位,后面七位作为数据位.它的存储范围在-128到127之间.

int整数类型的变量是16位的,最前一位为符号位,后面的15位作为数据位.它的存储范围在-215到215-1.也就是-32768到32767.它不包扩小数点以后的数,在一般编译器中给Int类型赋予带有小数的数.编译器会自动去掉小数点后面的数保留整数部分.

float为浮点数类型.首先要说明的是浮点数有两部分组成,第一部分是指数,也就是多少次幂嘛.第二部分是由尾数组成也就是一个数科学表示发之后除去幂那部分剩下的(呵呵!!!)如1.33333.那么C中的浮点数就有三部分.32位的浮点数第一位就是第一部分它决定数的符号.第二部分是八位的指数.第三部分是23位的尾数.所以浮点数具有6到7位的存储精确度.范围为3.4E-38到3.4E+38的数值.注:3.1415926E+7表示3.1415926.0.在给浮点数赋值的时候可以采用如下方法.123.45和1.2345E2是等价的.

double为双精度型变量.C编译器通常用64位来存储双精度性变量.它的精确度能够达到14到15位.64位中第一位是符号位.后面的11位是指数位.最后的52位是尾数.它的范围是-1.7E-308到1.7E+308.

类型标识符:unsigned,short,register,long和signed.

其中unsigned提示编译器不要保留符号位,这样可以扩大数据类型正数的范围.比如unsigned int的范围就变位0到65535了.

short类型用在有的编译器不能给太大的存储范围,需要给一个比较低的溢出界限.比如有的编译器就用的是32位来存储Int类型.用short来标识它可以保证int是用16位来标识的.

register表示一个变量可能会用得很频繁.需要很快得存取速度所以指定的把它存到寄存器当中.

long表示不希望用16位来存储整形变量时可以用long指定它用32位来存储可以得到更大得表示范围.

当然还有long unsigned int 这样得类型.

用户自定义数据类型

用户可以使用typedef来自己定义自己需要得数据类型.如下例:

typedef unsigned long int MYINT;

MYINT num1;

这样num1就是unsigned long int类型的了.

- 作者: goflyfreely 2005年09月3日, 星期六 11:31  回复(0) |  引用(1) 加入博采

竟然被卖!!
这个社会真是吃人的社会啊!我以为我生活在大厅广众之下就不会被卖了,结果我发现我和身边的人一起被卖了。

- 作者: goflyfreely 2005年06月2日, 星期四 23:31  回复(1) |  引用(1) 加入博采

长安乱中的一段话(幽默源至自然啊)

那人往下讲:后来,到了过沙,听说一个事情,厉害啊,原来,杀少林的是其它各大仇视帮派派出的高手,其中包括大漠第一腿的张富雄,武当暗器第一的牛三娃,金牛号称第一大力士的潭壮壮,等等等等好手,数都数不清,他们在酒楼里喝酒吹牛,结果一个少年,带了一把剑,那人不是人啊,是神。把少林灭了,触动了佛祖,佛祖派了身边一个点灯的下来,神兵天降啊,他们在二楼喝酒,那人不是从一楼上来的,是直接从天上降到二楼顶上,挖了个洞就下来了。
  众人哗然。
  那人说:那四十人当然不知道,说要打,那人都没动手,那四十个人就全死了。
  众人不信:胡说,不动手怎么杀人啊。
  那人说:笨蛋,动剑啊,不是说那人带了把剑吗?那剑是天上用来斩地削山用的,你看那太行山,都是用那剑削出来的。
  众人说:那四十人哪行啊。
  那人说:是啊,那剑,削金刚石就像削瓜一样。
  众人惊叹:削瓜!削瓜多容易啊。
  那人说:是啊,就跟削瓜一个样,不骗你,我看了大柱子上的断口。
  有人说:金刚石多硬啊,什么都弄不开,瓜多好削啊。
  又有人反对,说:胡说,瓜分好几种,我们胡瓜村种的瓜,就不好削,皮硬肉甜,特殊品种,进贡过皇上。
  旁人说:人那是天上的剑。
  那人说:那瓜大家都说是天瓜,那是十八年前,天上神仙不小心吃瓜的时候吐籽吐人间了,还就落在胡瓜村胡伯孙老人家田里,就长出这种瓜,和你们见过的瓜不一样,都是天上的东西,应该不能互相切。
  有人反对,说:胡说,人都是地上的东西,还不都互相杀。
  又有人说:那你那瓜今年收成好不好?
  那人说:别提了,那瓜好静,要慢慢长,今年不知咋的,野兔子特别多,老蹿那藤,搞得瓜长不好。
  有人说:那瓜长不好,就卖不出价钱了。
  一老汉捏捏胡子说:这你就不知道了,奇货可居,瓜少了,价钱就高了。
  有人说:高也高不过九年前跟鸡一个价。
  有人提议:至少和野兔子一个价钱。
  有人说:放屁,肯定是活的比死的贵。
  有人说:扯呢,野兔子不值钱。满地都是。
  有人说:野兔子难抓。
  有人说:难抓还难吃呢。
  说着说着,代表瓜贵和代表兔子贵的两方互相吵起来,互相不认输,纷纷列举出为什么兔子贵或为什么瓜贵,吵得面红耳赤,说野兔子贵的那方说了几句,说瓜贵那帮里突然就站起来一人,不知道从哪里抽出一把刀,大喊:老子就说是瓜贵,谁把野兔子卖贵了爷爷我砍了谁。
  然后众人大乱,抽刀的抽刀,掏匕首的掏匕首,还有抄起板凳就打的,互相厮杀成一团。我和喜乐事不关己,马上退出店外观望。里面真是空前混乱,几十人数十种武器打成一团,因为事先互相彼此不认识,阵营乱了以后就不知道谁是谁了,难免出现了认为兔子贵的打了一人半天,那人快断气前还说:你打死我我都说是兔子贵。遇到这样情况,只好忍痛将那人打死。打到后来,大家虽然都打红了眼,但还算理智,打前问:兔子还是瓜?发现一言不和才动手。有一兔子贵的问一陌生人:兔子还是瓜,那人要说,瓜怎能贵过兔子,刚说了一个字,就给一板凳拍晕了,场面惨不忍睹,说明关键时候讲话还是不要太注重修饰。打到最后,伤的伤,死的死,昏迷的昏迷,全都趴地上了,只剩下一个认为瓜贵的还能站着,那人爬桌上,要说什么,发现自己打迷糊了,不记得自己的立场到底是兔子贵还是瓜贵了,痛苦不已,突然认出下面有一个被自己打得奄奄一息的家伙,于是想到如果问那人是什么立场,自然就知道自己的立场了,便一步跨上前去,揪住那人,问:兔子还是瓜?那人本来立场是兔子贵,看见仇人又来了,为保一命,要和那壮士装作自己人,吓得忙改口,说:瓜,瓜贵。那人大笑,一拳打晕那人,又跳上台,对着一地伤员大喊:哈哈,还是兔子贵!
  这时候,下面有一个手脚都断了的瓜贵人士,认得桌上那人,知道他弄错自己立场了,提示道:兄弟,兄弟,你错了,是瓜贵。
  后果自然是说话那人被一刀杀了。我和喜乐看得目瞪口呆

  韩寒果然有天生搞笑的天分啊!不是恶俗的把幽默一下透露出来,而是委婉的道来,他写得有些夸张又似乎合情合理,不得不佩服他的文笔。

- 作者: goflyfreely 2005年05月24日, 星期二 23:51  回复(0) |  引用(1) 加入博采

我也搞个博客!

以前搞网页,太累!后来做FLASH,没成果!现在编程,太闷!唉!见大家都博客了,我也博客一回嘛!可是刚开始就犯了难,第一个目录取个啥名呢????想了半天,写我的生活吧,太普通。叫生活絮语吧,太酸。得!最后在想到了吃,于是在番茄炒鸡蛋一类的破名中选了个苦瓜,茄子,土豆出来。不容易啊!本来是要用番茄炒鸡蛋的,可是我不喜欢吃那东东,就没有用,我们也不能伤害人家啊!呵呵,看来我还是很善良的啊。不过现在留下的这三样可就是我最喜欢吃的东西了。本来以前很讨厌苦瓜的,太苦了放到嘴里就想吐出来。后来突发奇想有了想尝一下那种苦的滋味,在吃的时候尽量去体会苦的味道。后来不辛喜欢上了这种味道,所以现在它就在我所有喜欢的菜的首位了。至于茄子嘛!一直都喜欢,这个算是一种没有理由的喜欢嘛!喜欢的一种没有逻辑解释的情况!土豆--哈哈烧着吃,不过现在食堂把土豆烧成番薯一样,很有一套!服了他们了,好想有机会吃一次真正的烧土豆啊。

   什么都没讲先说到吃了啊!不是我好吃,是民以食为天。通俗一点说人最先讲的就是吃了。我不知道从这些能不能看出一个人的品位。不过我就喜欢这三样了,算是一俗人嘛。以上算是个开端了吧。

- 作者: goflyfreely 2005年05月24日, 星期二 22:55  回复(0) |  引用(1) 加入博采